tizen 2.3.1 release tizen_2.3.1 submit/tizen_2.3.1/20150915.081238 tizen_2.3.1_release
authorjk7744.park <jk7744.park@samsung.com>
Tue, 8 Sep 2015 13:27:49 +0000 (22:27 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Tue, 8 Sep 2015 13:27:49 +0000 (22:27 +0900)
95 files changed:
Makefile.am
audioeq/Makefile.am [new file with mode: 0755]
audioeq/src/Makefile.am [new file with mode: 0755]
audioeq/src/gstaudioeq.c [new file with mode: 0755]
audioeq/src/gstaudioeq.h [new file with mode: 0644]
audiotp/src/gstaudiotp.c
avsystem/src/Makefile.am [deleted file]
avsystem/src/gstavsysaudiosink.c [deleted file]
avsystem/src/gstavsysaudiosink.h [deleted file]
avsystem/src/gstavsysaudiosrc.c [deleted file]
avsystem/src/gstavsysaudiosrc.h [deleted file]
avsystem/src/gstavsysmemsink.c [deleted file]
avsystem/src/gstavsysmemsink.h [deleted file]
avsystem/src/gstavsyssink.c [deleted file]
avsystem/src/gstavsyssrc.c [deleted file]
common/m4/gst-x11.m4 [new file with mode: 0644]
compile [new file with mode: 0755]
config.guess [new file with mode: 0755]
config.h.in [new file with mode: 0644]
configure.ac
dashdemux/Makefile.am [new file with mode: 0755]
dashdemux/src/Makefile.am [new file with mode: 0644]
dashdemux/src/Makefile.in [new file with mode: 0644]
dashdemux/src/glibcompat.h [new file with mode: 0755]
dashdemux/src/gstdashdemux.c [new file with mode: 0755]
dashdemux/src/gstdashdemux.h [new file with mode: 0755]
dashdemux/src/gstdownloadrate.c [new file with mode: 0644]
dashdemux/src/gstdownloadrate.h [new file with mode: 0644]
dashdemux/src/gstfragment.c [new file with mode: 0755]
dashdemux/src/gstfragment.h [new file with mode: 0755]
dashdemux/src/gstfragmented.h [new file with mode: 0755]
dashdemux/src/gstmpdparser.c [new file with mode: 0755]
dashdemux/src/gstmpdparser.h [new file with mode: 0755]
dashdemux/src/gstplugin.c [new file with mode: 0755]
dashdemux/src/gsturidownloader.c [new file with mode: 0755]
dashdemux/src/gsturidownloader.h [new file with mode: 0755]
debian/changelog [new file with mode: 0755]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0755]
debian/copyright [new file with mode: 0644]
debian/gstreamer0.10-plugins-ext.install.in [new file with mode: 0644]
debian/rules [new file with mode: 0755]
drmsrc/src/Makefile.am
drmsrc/src/drm_util.c [new file with mode: 0755]
drmsrc/src/drm_util.h [new file with mode: 0755]
drmsrc/src/gstdrmsrc.c
drmsrc/src/gstdrmsrc.h
encodebin/src/gstencodebin.c [changed mode: 0644->0755]
encodebin/src/gstencodebin.h
evasimagesink/src/Makefile.am
evasimagesink/src/gstevasimagesink.c [changed mode: 0644->0755]
evasimagesink/src/gstevasimagesink.h [changed mode: 0644->0755]
evaspixmapsink/Makefile.am [new file with mode: 0644]
evaspixmapsink/evaspixmapsink.c [new file with mode: 0755]
evaspixmapsink/evaspixmapsink.h [new file with mode: 0755]
evaspixmapsink/xv_types.h [new file with mode: 0644]
gst-plugins-ext0.10.manifest [new file with mode: 0755]
hlsdemux2/Makefile.am [new file with mode: 0755]
hlsdemux2/predefined_frame/blackframe_QVGA.264 [new file with mode: 0755]
hlsdemux2/predefined_frame/sec_audio_fixed_qvga.264 [new file with mode: 0755]
hlsdemux2/predefined_frame/sec_audio_fixed_qvga.jpg [new file with mode: 0755]
hlsdemux2/src/Makefile.am [new file with mode: 0755]
hlsdemux2/src/gsthlsdemux2.c [new file with mode: 0755]
hlsdemux2/src/gsthlsdemux2.h [new file with mode: 0755]
hlsdemux2/src/m3u8.c [new file with mode: 0755]
hlsdemux2/src/m3u8.h [new file with mode: 0755]
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/src/gstssdemux.c
ssdemux/src/gstssdemux.h
ssdemux/src/ssmanifestparse.c
ssdemux/src/ssmanifestparse.h
submux/Makefile.am [new file with mode: 0755]
submux/src/Makefile.am [new file with mode: 0755]
submux/src/gstsubmux.c [new file with mode: 0755]
submux/src/gstsubmux.h [new file with mode: 0755]
toggle/src/gsttoggle.c
xvimagesrc/Makefile.am [moved from avsystem/Makefile.am with 100% similarity]
xvimagesrc/src/Makefile.am [new file with mode: 0644]
xvimagesrc/src/gstxvimagesrc.c [new file with mode: 0755]
xvimagesrc/src/gstxvimagesrc.h [new file with mode: 0755]
xvimagesrc/src/xv_types.h [new file with mode: 0644]

index 3115751..e75ed8c 100755 (executable)
@@ -5,27 +5,37 @@ aclocaldir = $(datadir)/aclocal
 
 SUBDIRS = common
 
-if GST_EXT_USE_EXT_ENCODEBIN
-SUBDIRS += encodebin
+if GST_EXT_USE_EXT_PIFFDEMUX
+SUBDIRS += piffdemux
 endif
 
-if GST_EXT_USE_EXT_AVSYSTEM
-SUBDIRS += avsystem
+if GST_EXT_USE_EXT_ENCODEBIN
+SUBDIRS += encodebin
 endif
 
 if GST_EXT_USE_EXT_EVASIMAGESINK
 SUBDIRS += evasimagesink
 endif
 
+if GST_EXT_USE_EXT_EVASPIXMAPSINK
+SUBDIRS += evaspixmapsink
+endif
+
+if GST_EXT_USE_EXT_XVIMAGESRC
+SUBDIRS += xvimagesrc
+endif
+
 if GST_EXT_USE_EXT_DRMSRC
 SUBDIRS += drmsrc
 endif
-
+if GST_EXT_USE_EXT_SUBMUX
+SUBDIRS += submux
+endif
 if GST_EXT_USE_EXT_TOGGLE
 SUBDIRS += toggle
 endif
 
-if GST_EXT_USE_EXT_AVSYSTEM
+if GST_EXT_USE_EXT_PD_PUSHSRC
 SUBDIRS += pdpushsrc
 endif
 
@@ -33,39 +43,61 @@ if GST_EXT_USE_EXT_AUDIOTP
 SUBDIRS += audiotp
 endif
 
+if GST_EXT_USE_EXT_AUDIOEQ
+SUBDIRS += audioeq
+endif
+
 if GST_EXT_USE_EXT_SSDEMUX
-#SUBDIRS += ssdemux
+SUBDIRS += ssdemux
 endif
 
+if GST_EXT_USE_EXT_DASHDEMUX
+SUBDIRS += dashdemux
+endif
 
+if GST_EXT_USE_EXT_HLSDEMUX2
+SUBDIRS += hlsdemux2
+endif
 
 DIST_SUBDIRS = common
 
-if GST_EXT_USE_EXT_ENCODEBIN
-DIST_SUBDIRS += encodebin
+if GST_EXT_USE_EXT_PIFFDEMUX
+DIST_SUBDIRS += piffdemux
 endif
 
-if GST_EXT_USE_EXT_AVSYSTEM
-DIST_SUBDIRS += avsystem
+if GST_EXT_USE_EXT_ENCODEBIN
+DIST_SUBDIRS += encodebin
 endif
 
 if GST_EXT_USE_EXT_EVASIMAGESINK
 DIST_SUBDIRS += evasimagesink
 endif
 
+if GST_EXT_USE_EXT_XVIMAGESRC
+DIST_SUBDIRS += xvimagesrc
+endif
+
 if GST_EXT_USE_EXT_DRMSRC
 DIST_SUBDIRS += drmsrc
 endif
-
+if GST_EXT_USE_EXT_SUBMUX
+DIST_SUBDIRS += submux
+endif
 if GST_EXT_USE_EXT_TOGGLE
 DIST_SUBDIRS += toggle
 endif
 
 if GST_EXT_USE_EXT_SSDEMUX
-#DIST_SUBDIRS += ssdemux
+DIST_SUBDIRS += ssdemux
 endif
 
+if GST_EXT_USE_EXT_DASHDEMUX
+DIST_SUBDIRS += dashdemux
+endif
 
+if GST_EXT_USE_EXT_HLSDEMUX2
+DIST_SUBDIRS += hlsdemux2
+endif
 
 EXTRA_DIST = \
        gstreamer.spec gstreamer.spec.in \
diff --git a/audioeq/Makefile.am b/audioeq/Makefile.am
new file mode 100755 (executable)
index 0000000..308a09c
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = src\r
diff --git a/audioeq/src/Makefile.am b/audioeq/src/Makefile.am
new file mode 100755 (executable)
index 0000000..6981e78
--- /dev/null
@@ -0,0 +1,28 @@
+# plugindir is set in configure
+
+##############################################################################
+# change libgstplugin.la to something more suitable, e.g. libmysomething.la  #
+##############################################################################
+plugin_LTLIBRARIES = libgstaudioeq.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
+libgstaudioeq_la_SOURCES = gstaudioeq.c
+
+# flags used to compile this plugin
+# add other _CFLAGS and _LIBS as needed
+libgstaudioeq_la_CFLAGS = $(GST_CFLAGS)  $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CONTROLLER_CFLAGS)
+libgstaudioeq_la_LIBADD = $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(GST_BASE_LIBS) $(GST_CONTROLLER_LIBS) $(GST_LIBS) $(LIBM) -lgstbase-0.10  -lglib-2.0 -lgstcontroller-0.10
+libgstaudioeq_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+
+libgstequalizer_la_LIBTOOLFLAGS = --tag=disable-static
+
+# headers we need but don't want installed
+noinst_HEADERS = gstaudioeq.h
diff --git a/audioeq/src/gstaudioeq.c b/audioeq/src/gstaudioeq.c
new file mode 100755 (executable)
index 0000000..3c36e4a
--- /dev/null
@@ -0,0 +1,1313 @@
+/*
+ * audioeq
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Aditi Narula <aditi.n@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 "gstaudioeq.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_audioeq_debug);
+#define GST_CAT_DEFAULT gst_audioeq_debug
+
+#define AUDIOEQ_ENABLE_DUMP
+#define AUDIOEQ_REDUCE_MEMCPY
+
+/* Filter signals and args */
+enum
+{
+       /* FILL ME */
+       LAST_SIGNAL
+};
+
+enum
+{
+       PROP_0,
+       PROP_FILTER_ACTION,
+       PROP_CUSTOM_EQ,
+       PROP_CUSTOM_EQ_NUM,
+       PROP_CUSTOM_EQ_FREQ,
+       PROP_CUSTOM_EQ_WIDTH,
+};
+
+enum FilterActionType
+{
+       FILTER_NONE,
+       FILTER_PRESET,
+       FILTER_ADVANCED_SETTING
+};
+
+enum SampleRate
+{
+       SAMPLERATE_48000Hz,
+       SAMPLERATE_44100Hz,
+       SAMPLERATE_32000Hz,
+       SAMPLERATE_24000Hz,
+       SAMPLERATE_22050Hz,
+       SAMPLERATE_16000Hz,
+       SAMPLERATE_12000Hz,
+       SAMPLERATE_11025Hz,
+       SAMPLERATE_8000Hz,
+
+       SAMPLERATE_NUM
+};
+
+#define DEFAULT_SAMPLE_SIZE                    2
+#define DEFAULT_VOLUME                                 15
+#define DEFAULT_GAIN                                   1
+#define DEFAULT_SAMPLE_RATE                    SAMPLERATE_44100Hz
+#define DEAFULT_CHANNELS                               2
+#define DEFAULT_FILTER_ACTION                  FILTER_NONE
+#define DEFAULT_CUSTOM_EQ_NUM          7
+
+static GstStaticPadTemplate sinktemplate =
+       GST_STATIC_PAD_TEMPLATE(
+               "sink",
+               GST_PAD_SINK,
+               GST_PAD_ALWAYS,
+               GST_STATIC_CAPS (
+                       "audio/x-raw-int, "
+                       "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
+                       "signed = (boolean) true, "
+                       "width = (int) 16, "
+                       "depth = (int) 16, "
+                       "channels = (int) [1,2]"
+                       )
+       );
+
+static GstStaticPadTemplate srctemplate =
+       GST_STATIC_PAD_TEMPLATE(
+               "src",
+               GST_PAD_SRC,
+               GST_PAD_ALWAYS,
+               GST_STATIC_CAPS (
+                       "audio/x-raw-int, "
+                       "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
+                       "signed = (boolean) true, "
+                       "width = (int) 16, "
+                       "depth = (int) 16, "
+                       "channels = (int) [1,2]"
+                       )
+       );
+
+static void gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface,
+    gpointer iface_data);
+
+static void gst_iir_equalizer_finalize (GObject * object);
+
+static gboolean gst_iir_equalizer_setup (GstAudioFilter * filter,
+    GstRingBufferSpec * fmt);
+
+static void
+_do_init (GType object_type)
+{
+  const GInterfaceInfo child_proxy_interface_info = {
+    (GInterfaceInitFunc) gst_iir_equalizer_child_proxy_interface_init,
+    NULL,                       /* interface_finalize */
+    NULL                        /* interface_data */
+  };
+
+  g_type_add_interface_static (object_type, GST_TYPE_CHILD_PROXY,
+      &child_proxy_interface_info);
+}
+
+GST_BOILERPLATE_FULL(Gstaudioeq, gst_audioeq, GstBaseTransform, GST_TYPE_BASE_TRANSFORM,_do_init);
+
+static void gst_audioeq_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_audioeq_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
+#ifdef AUDIOEQ_REDUCE_MEMCPY
+static GstFlowReturn gst_audioeq_transform_ip (GstBaseTransform * base, GstBuffer * buf);
+#else
+static GstFlowReturn gst_audioeq_transform (GstBaseTransform * base, GstBuffer * inbuf, GstBuffer * outbuf);
+#endif
+static gboolean gst_audioeq_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps);
+
+static GstStateChangeReturn
+gst_audioeq_change_state (GstElement * element, GstStateChange transition)
+{
+  GST_DEBUG ("gst_audioeq_change_state");
+       GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+       Gstaudioeq *audioeq = GST_AUDIOEQ (element);
+
+       switch (transition) {
+       case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+               audioeq->need_update_filter = TRUE;
+               break;
+       default:
+               break;
+       }
+
+       ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+       if (ret == GST_STATE_CHANGE_FAILURE)
+               return ret;
+
+       switch (transition) {
+       case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static void
+gst_audioeq_base_init (gpointer gclass)
+{
+
+  GST_DEBUG ("gst_audioeq_base_init");
+       static GstElementDetails element_details = {
+               "Audio Equalizer",
+               "Filter/Effect/Audio",
+               "Set equalisation effect on audio/raw streams",
+               "Samsung Electronics <www.samsung.com>"
+       };
+
+       GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
+
+       gst_element_class_add_pad_template(element_class,
+               gst_static_pad_template_get (&srctemplate));
+       gst_element_class_add_pad_template(element_class,
+               gst_static_pad_template_get (&sinktemplate));
+
+       gst_element_class_set_details(element_class, &element_details);
+}
+
+static void
+gst_audioeq_class_init (GstaudioeqClass * klass)
+{
+       GST_DEBUG ("gst_audioeq_class_init");
+       GObjectClass *gobject_class;
+       GstElementClass *gstelement_class;
+       GstBaseTransformClass *basetransform_class;
+
+       gobject_class = G_OBJECT_CLASS (klass);
+       gstelement_class = GST_ELEMENT_CLASS (klass);
+       basetransform_class = GST_BASE_TRANSFORM_CLASS(klass);
+
+       gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_audioeq_set_property);
+       gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_audioeq_get_property);
+
+       gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_audioeq_change_state);
+
+       g_object_class_install_property(gobject_class, PROP_FILTER_ACTION,
+               g_param_spec_uint("filter-action", "filter action", "(0)none (1)preset (2)advanced setting",
+               0, 2, DEFAULT_FILTER_ACTION, G_PARAM_READWRITE));
+
+       g_object_class_install_property (gobject_class, PROP_CUSTOM_EQ,
+               g_param_spec_pointer("custom-eq", "custom eq",
+               "pointer for 9 bands of EQ array", G_PARAM_READWRITE));
+
+       g_object_class_install_property(gobject_class, PROP_CUSTOM_EQ_NUM,
+               g_param_spec_uint("custom-eq-num", "custom eq num", "number of custom EQ bands",
+               0, 9, DEFAULT_CUSTOM_EQ_NUM, G_PARAM_READABLE));
+
+       g_object_class_install_property(gobject_class, PROP_CUSTOM_EQ_FREQ,
+               g_param_spec_pointer("custom-eq-freq", "custom eq freq", "pointer for EQ bands central frequency(Hz) array",
+               G_PARAM_READABLE));
+
+       g_object_class_install_property(gobject_class, PROP_CUSTOM_EQ_WIDTH,
+               g_param_spec_pointer("custom-eq-width", "custom eq width", "pointer for EQ bands width(Hz) array",
+               G_PARAM_READABLE));
+
+       gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_iir_equalizer_finalize);
+
+/* It is possible to reduce memcpy by setting output same as input of AudioEq_InOutConfig */
+#ifdef AUDIOEQ_REDUCE_MEMCPY
+       basetransform_class->transform_ip = GST_DEBUG_FUNCPTR(gst_audioeq_transform_ip);
+#endif
+       basetransform_class->set_caps = GST_DEBUG_FUNCPTR(gst_audioeq_set_caps);
+}
+
+static void
+gst_audioeq_init (Gstaudioeq * audioeq, GstaudioeqClass * gclass)
+{
+  GST_DEBUG ("gst_audioeq_init");
+       audioeq->samplerate = DEFAULT_SAMPLE_RATE;
+       audioeq->channels = DEAFULT_CHANNELS;
+
+       audioeq->filter_action = DEFAULT_FILTER_ACTION;
+       memset(audioeq->custom_eq, 0x00, sizeof(gint) * CUSTOM_EQ_BAND_MAX);
+       audioeq->need_update_filter = TRUE;
+       audioeq->equ.bands_lock = g_mutex_new ();
+       audioeq->equ.need_new_coefficients = TRUE;
+       gst_iir_equalizer_compute_frequencies (audioeq, DEFAULT_CUSTOM_EQ_NUM);
+}
+/* equalizer implementation */
+
+static void
+gst_iir_equalizer_finalize (GObject * object)
+{
+  GST_DEBUG ("gst_iir_equalizer_finalize");
+  Gstaudioeq *audioeq = GST_AUDIOEQ(object);
+  GstIirEqualizer *equ = &audioeq->equ;
+  gint i;
+
+  for (i = 0; i < equ->freq_band_count; i++) {
+    if (equ->bands[i])
+      gst_object_unparent (GST_OBJECT (equ->bands[i]));
+    equ->bands[i] = NULL;
+  }
+  equ->freq_band_count = 0;
+
+  g_free (equ->bands);
+  g_free (equ->history);
+
+  g_mutex_free (equ->bands_lock);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+#define BANDS_LOCK(equ) g_mutex_lock(equ->bands_lock)
+#define BANDS_UNLOCK(equ) g_mutex_unlock(equ->bands_lock)
+
+/* child object */
+
+enum
+{
+  PROP_GAIN = 1,
+  PROP_FREQ,
+  PROP_BANDWIDTH,
+  PROP_TYPE
+};
+
+typedef enum
+{
+  BAND_TYPE_PEAK = 0,
+  BAND_TYPE_LOW_SHELF,
+  BAND_TYPE_HIGH_SHELF
+} GstIirEqualizerBandType;
+
+#define GST_TYPE_IIR_EQUALIZER_BAND_TYPE (gst_iir_equalizer_band_type_get_type ())
+static GType
+gst_iir_equalizer_band_type_get_type (void)
+{
+  GST_DEBUG ("gst_iir_equalizer_band_type_get_type");
+  static GType gtype = 0;
+
+  if (gtype == 0) {
+    static const GEnumValue values[] = {
+      {BAND_TYPE_PEAK, "Peak filter (default for inner bands)", "peak"},
+      {BAND_TYPE_LOW_SHELF, "Low shelf filter (default for first band)",
+          "low-shelf"},
+      {BAND_TYPE_HIGH_SHELF, "High shelf filter (default for last band)",
+          "high-shelf"},
+      {0, NULL, NULL}
+    };
+
+    gtype = g_enum_register_static ("GstIirEqualizerBandType", values);
+  }
+  return gtype;
+}
+
+
+typedef struct _GstIirEqualizerBandClass GstIirEqualizerBandClass;
+
+#define GST_TYPE_IIR_EQUALIZER_BAND \
+  (gst_iir_equalizer_band_get_type())
+#define GST_IIR_EQUALIZER_BAND(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IIR_EQUALIZER_BAND,GstIirEqualizerBand))
+#define GST_IIR_EQUALIZER_BAND_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IIR_EQUALIZER_BAND,GstIirEqualizerBandClass))
+#define GST_IS_IIR_EQUALIZER_BAND(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IIR_EQUALIZER_BAND))
+#define GST_IS_IIR_EQUALIZER_BAND_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IIR_EQUALIZER_BAND))
+
+struct _GstIirEqualizerBand
+{
+  GstObject object;
+
+  /*< private > */
+  /* center frequency and gain */
+  gdouble freq;
+  gdouble gain;
+  gdouble width;
+  GstIirEqualizerBandType type;
+
+  /* second order iir filter */
+  gdouble b1, b2;               /* IIR coefficients for outputs */
+  gdouble a0, a1, a2;           /* IIR coefficients for inputs */
+};
+
+struct _GstIirEqualizerBandClass
+{
+  GstObjectClass parent_class;
+};
+
+static GType gst_iir_equalizer_band_get_type (void);
+
+static void
+gst_iir_equalizer_band_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GST_DEBUG ("gst_iir_equalizer_band_set_property");
+  GstIirEqualizerBand *band = GST_IIR_EQUALIZER_BAND (object);
+  Gstaudioeq *audioeq = GST_AUDIOEQ (gst_object_get_parent (GST_OBJECT (band)));
+  GstIirEqualizer *equ = &audioeq->equ;
+
+  switch (prop_id) {
+    case PROP_GAIN:{
+      gdouble gain;
+
+      gain = g_value_get_double (value);
+      GST_DEBUG_OBJECT (band, "gain = %lf -> %lf", band->gain, gain);
+      if (gain != band->gain) {
+        BANDS_LOCK (equ);
+        equ->need_new_coefficients = TRUE;
+        band->gain = gain;
+        BANDS_UNLOCK (equ);
+        GST_DEBUG_OBJECT (band, "changed gain = %lf ", band->gain);
+      }
+      break;
+    }
+    case PROP_FREQ:{
+      gdouble freq;
+
+      freq = g_value_get_double (value);
+      GST_DEBUG_OBJECT (band, "freq = %lf -> %lf", band->freq, freq);
+      if (freq != band->freq) {
+        BANDS_LOCK (equ);
+        equ->need_new_coefficients = TRUE;
+        band->freq = freq;
+        BANDS_UNLOCK (equ);
+        GST_DEBUG_OBJECT (band, "changed freq = %lf ", band->freq);
+      }
+      break;
+    }
+    case PROP_BANDWIDTH:{
+      gdouble width;
+
+      width = g_value_get_double (value);
+      GST_DEBUG_OBJECT (band, "width = %lf -> %lf", band->width, width);
+      if (width != band->width) {
+        BANDS_LOCK (equ);
+        equ->need_new_coefficients = TRUE;
+        band->width = width;
+        BANDS_UNLOCK (equ);
+        GST_DEBUG_OBJECT (band, "changed width = %lf ", band->width);
+      }
+      break;
+    }
+    case PROP_TYPE:{
+      GstIirEqualizerBandType type;
+
+      type = g_value_get_enum (value);
+      GST_DEBUG_OBJECT (band, "type = %d -> %d", band->type, type);
+      if (type != band->type) {
+        BANDS_LOCK (equ);
+        equ->need_new_coefficients = TRUE;
+        band->type = type;
+        BANDS_UNLOCK (equ);
+        GST_DEBUG_OBJECT (band, "changed type = %d ", band->type);
+      }
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+
+  gst_object_unref (audioeq);
+}
+
+static void
+gst_iir_equalizer_band_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GST_DEBUG ("gst_iir_equalizer_band_get_property");
+  GstIirEqualizerBand *band = GST_IIR_EQUALIZER_BAND (object);
+
+  switch (prop_id) {
+    case PROP_GAIN:
+      g_value_set_double (value, band->gain);
+      break;
+    case PROP_FREQ:
+      g_value_set_double (value, band->freq);
+      break;
+    case PROP_BANDWIDTH:
+      g_value_set_double (value, band->width);
+      break;
+    case PROP_TYPE:
+      g_value_set_enum (value, band->type);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_iir_equalizer_band_class_init (GstIirEqualizerBandClass * klass)
+{
+  GST_DEBUG ("gst_iir_equalizer_band_class_init");
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->set_property = gst_iir_equalizer_band_set_property;
+  gobject_class->get_property = gst_iir_equalizer_band_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_GAIN,
+      g_param_spec_double ("gain", "gain",
+          "gain for the frequency band ranging from -12.0 dB to +12.0 dB",
+          -12.0, 12.0, 0.0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_FREQ,
+      g_param_spec_double ("freq", "freq",
+          "center frequency of the band",
+          0.0, 100000.0, 0.0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_BANDWIDTH,
+      g_param_spec_double ("bandwidth", "bandwidth",
+          "difference between bandedges in Hz",
+          0.0, 100000.0, 1.0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_TYPE,
+      g_param_spec_enum ("type", "Type",
+          "Filter type", GST_TYPE_IIR_EQUALIZER_BAND_TYPE,
+          BAND_TYPE_PEAK,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
+}
+
+static void
+gst_iir_equalizer_band_init (GstIirEqualizerBand * band,
+    GstIirEqualizerBandClass * klass)
+{
+  GST_DEBUG ("gst_iir_equalizer_band_init");
+  band->freq = 0.0;
+  band->gain = 0.0;
+  band->width = 1.0;
+  band->type = BAND_TYPE_PEAK;
+}
+
+static GType
+gst_iir_equalizer_band_get_type (void)
+{
+  GST_DEBUG ("gst_iir_equalizer_band_get_type");
+  static GType type = 0;
+
+  if (G_UNLIKELY (!type)) {
+    const GTypeInfo type_info = {
+      sizeof (GstIirEqualizerBandClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) gst_iir_equalizer_band_class_init,
+      NULL,
+      NULL,
+      sizeof (GstIirEqualizerBand),
+      0,
+      (GInstanceInitFunc) gst_iir_equalizer_band_init,
+    };
+    type =
+        g_type_register_static (GST_TYPE_OBJECT, "GstIirEqualizerBand",
+        &type_info, 0);
+  }
+  return (type);
+}
+
+
+/* child proxy iface */
+static GstObject *
+gst_iir_equalizer_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
+    guint index)
+{
+  GST_DEBUG ("gst_iir_equalizer_child_proxy_get_child_by_index");
+  Gstaudioeq *audioeq = GST_AUDIOEQ(child_proxy);
+  GstIirEqualizer *equ = &audioeq->equ;
+  GstObject *ret;
+
+  BANDS_LOCK (equ);
+  if (G_UNLIKELY (index >= equ->freq_band_count)) {
+    BANDS_UNLOCK (equ);
+    g_return_val_if_fail (index < equ->freq_band_count, NULL);
+  }
+
+  ret = gst_object_ref (equ->bands[index]);
+  BANDS_UNLOCK (equ);
+
+  GST_LOG_OBJECT (equ, "return child[%d] %" GST_PTR_FORMAT, index, ret);
+  return ret;
+}
+
+static guint
+gst_iir_equalizer_child_proxy_get_children_count (GstChildProxy * child_proxy)
+{
+  GST_DEBUG ("gst_iir_equalizer_child_proxy_get_children_count");
+  Gstaudioeq *audioeq = GST_AUDIOEQ(child_proxy);
+  GstIirEqualizer *equ = &audioeq->equ;
+
+  GST_LOG ("we have %d children", equ->freq_band_count);
+  return equ->freq_band_count;
+}
+
+static void
+gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface,
+    gpointer iface_data)
+{
+  GstChildProxyInterface *iface = g_iface;
+
+  GST_DEBUG ("initializing iface");
+
+  iface->get_child_by_index = gst_iir_equalizer_child_proxy_get_child_by_index;
+  iface->get_children_count = gst_iir_equalizer_child_proxy_get_children_count;
+}
+static void
+gst_iir_equalizer_class_init (GstIirEqualizerClass * klass)
+{
+  GST_DEBUG ("gst_iir_equalizer_class_init");
+}
+
+static void
+gst_iir_equalizer_init (GstIirEqualizer * eq, GstIirEqualizerClass * g_class)
+{
+  GST_DEBUG ("gst_iir_equalizer_init");
+  eq->bands_lock = g_mutex_new ();
+  eq->need_new_coefficients = TRUE;
+}
+
+GType
+gst_iir_equalizer_get_type (void)
+{
+  GST_DEBUG ("gst_iir_equalizer_get_type");
+  static GType type = 0;
+
+  if (G_UNLIKELY (!type)) {
+    const GTypeInfo type_info = {
+      sizeof (GstIirEqualizerClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) gst_iir_equalizer_class_init,
+      NULL,
+      NULL,
+      sizeof (GstIirEqualizer),
+      0,
+      (GInstanceInitFunc) gst_iir_equalizer_init,
+    };
+    type =
+        g_type_register_static (GST_TYPE_OBJECT, "GstIirEqualizer",
+        &type_info, 0);
+  }
+  return (type);
+}
+/* Filter taken from
+ *
+ * The Equivalence of Various Methods of Computing
+ * Biquad Coefficients for Audio Parametric Equalizers
+ *
+ * by Robert Bristow-Johnson
+ *
+ * http://www.aes.org/e-lib/browse.cfm?elib=6326
+ * http://www.musicdsp.org/files/EQ-Coefficients.pdf
+ * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
+ *
+ * The bandwidth method that we use here is the preferred
+ * one from this article transformed from octaves to frequency
+ * in Hz.
+ */
+static inline gdouble
+arg_to_scale (gdouble arg)
+{
+  GST_DEBUG ("arg_to_scale");
+  return (pow (10.0, arg / 40.0));
+}
+
+static gdouble
+calculate_omega (gdouble freq, gint rate)
+{
+  GST_DEBUG ("calculate_omega");
+  gdouble omega;
+
+  if (freq / rate >= 0.5)
+    omega = G_PI;
+  else if (freq <= 0.0)
+    omega = 0.0;
+  else
+    omega = 2.0 * G_PI * (freq / rate);
+
+  return omega;
+}
+
+static gdouble
+calculate_bw (GstIirEqualizerBand * band, gint rate)
+{
+  GST_DEBUG ("calculate_bw");
+  gdouble bw = 0.0;
+
+  if (band->width / rate >= 0.5) {
+    /* If bandwidth == 0.5 the calculation below fails as tan(G_PI/2)
+     * is undefined. So set the bandwidth to a slightly smaller value.
+     */
+    bw = G_PI - 0.00000001;
+  } else if (band->width <= 0.0) {
+    /* If bandwidth == 0 this band won't change anything so set
+     * the coefficients accordingly. The coefficient calculation
+     * below would create coefficients that for some reason amplify
+     * the band.
+     */
+    band->a0 = 1.0;
+    band->a1 = 0.0;
+    band->a2 = 0.0;
+    band->b1 = 0.0;
+    band->b2 = 0.0;
+  } else {
+    bw = 2.0 * G_PI * (band->width / rate);
+  }
+  return bw;
+}
+
+static void
+setup_peak_filter (Gstaudioeq* audioeq, GstIirEqualizerBand * band)
+{
+  GST_DEBUG ("setup_peak_filter");
+  //g_return_if_fail (GST_AUDIO_FILTER (equ)->format.rate);
+
+  {
+    gdouble gain, omega, bw;
+    gdouble alpha, alpha1, alpha2, b0;
+
+    gain = arg_to_scale (band->gain);
+    omega = calculate_omega (band->freq, audioeq->samplerate);
+    bw = calculate_bw (band, audioeq->samplerate);
+    if (bw == 0.0)
+      goto out;
+
+    alpha = tan (bw / 2.0);
+
+    alpha1 = alpha * gain;
+    alpha2 = alpha / gain;
+
+    b0 = (1.0 + alpha2);
+
+    band->a0 = (1.0 + alpha1) / b0;
+    band->a1 = (-2.0 * cos (omega)) / b0;
+    band->a2 = (1.0 - alpha1) / b0;
+    band->b1 = (2.0 * cos (omega)) / b0;
+    band->b2 = -(1.0 - alpha2) / b0;
+
+  out:
+    GST_INFO
+        ("gain = %5.1f, width= %7.2f, freq = %7.2f, a0 = %7.5g, a1 = %7.5g, a2=%7.5g b1 = %7.5g, b2 = %7.5g",
+        band->gain, band->width, band->freq, band->a0, band->a1, band->a2,
+        band->b1, band->b2);
+  }
+}
+
+static void
+setup_low_shelf_filter (Gstaudioeq* audioeq, GstIirEqualizerBand * band)
+{
+  GST_DEBUG ("setup_low_shelf_filter");
+  //g_return_if_fail (GST_AUDIO_FILTER (equ)->format.rate);
+
+  {
+    gdouble gain, omega, bw;
+    gdouble alpha, delta, b0;
+    gdouble egp, egm;
+
+    gain = arg_to_scale (band->gain);
+    omega = calculate_omega (band->freq, audioeq->samplerate);
+    bw = calculate_bw (band, audioeq->samplerate);
+    if (bw == 0.0)
+      goto out;
+
+    egm = gain - 1.0;
+    egp = gain + 1.0;
+    alpha = tan (bw / 2.0);
+
+    delta = 2.0 * sqrt (gain) * alpha;
+    b0 = egp + egm * cos (omega) + delta;
+
+    band->a0 = ((egp - egm * cos (omega) + delta) * gain) / b0;
+    band->a1 = ((egm - egp * cos (omega)) * 2.0 * gain) / b0;
+    band->a2 = ((egp - egm * cos (omega) - delta) * gain) / b0;
+    band->b1 = ((egm + egp * cos (omega)) * 2.0) / b0;
+    band->b2 = -((egp + egm * cos (omega) - delta)) / b0;
+
+
+  out:
+    GST_INFO
+        ("gain = %5.1f, width= %7.2f, freq = %7.2f, a0 = %7.5g, a1 = %7.5g, a2=%7.5g b1 = %7.5g, b2 = %7.5g",
+        band->gain, band->width, band->freq, band->a0, band->a1, band->a2,
+        band->b1, band->b2);
+  }
+}
+
+static void
+setup_high_shelf_filter (Gstaudioeq* audioeq, GstIirEqualizerBand * band)
+{
+  GST_DEBUG ("setup_high_shelf_filter");
+  {
+    gdouble gain, omega, bw;
+    gdouble alpha, delta, b0;
+    gdouble egp, egm;
+
+    gain = arg_to_scale (band->gain);
+    omega = calculate_omega (band->freq, audioeq->samplerate);
+    bw = calculate_bw (band, audioeq->samplerate);
+    if (bw == 0.0)
+      goto out;
+
+    egm = gain - 1.0;
+    egp = gain + 1.0;
+    alpha = tan (bw / 2.0);
+
+    delta = 2.0 * sqrt (gain) * alpha;
+    b0 = egp - egm * cos (omega) + delta;
+
+    band->a0 = ((egp + egm * cos (omega) + delta) * gain) / b0;
+    band->a1 = ((egm + egp * cos (omega)) * -2.0 * gain) / b0;
+    band->a2 = ((egp + egm * cos (omega) - delta) * gain) / b0;
+    band->b1 = ((egm - egp * cos (omega)) * -2.0) / b0;
+    band->b2 = -((egp - egm * cos (omega) - delta)) / b0;
+
+
+  out:
+    GST_INFO
+        ("gain = %5.1f, width= %7.2f, freq = %7.2f, a0 = %7.5g, a1 = %7.5g, a2=%7.5g b1 = %7.5g, b2 = %7.5g",
+        band->gain, band->width, band->freq, band->a0, band->a1, band->a2,
+        band->b1, band->b2);
+  }
+}
+
+/* Must be called with bands_lock and transform lock! */
+static void
+set_passthrough (Gstaudioeq* audioeq)
+{
+  GST_DEBUG ("set_passthrough");
+  GstIirEqualizer* equ=&audioeq->equ;
+  gint i;
+  gboolean passthrough = TRUE;
+
+  for (i = 0; i < equ->freq_band_count; i++) {
+    passthrough = passthrough && (equ->bands[i]->gain == 0.0);
+  }
+
+  gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (audioeq), passthrough);
+  GST_DEBUG ("Passthrough mode: %d\n", passthrough);
+}
+
+/* Must be called with bands_lock and transform lock! */
+static void
+update_coefficients (Gstaudioeq* audioeq)
+{
+  GST_DEBUG ("update_coefficients");
+  GstIirEqualizer* equ=&audioeq->equ;
+  gint i, n = equ->freq_band_count;
+
+  for (i = 0; i < n; i++) {
+    if (equ->bands[i]->type == BAND_TYPE_PEAK)
+      setup_peak_filter (audioeq, equ->bands[i]);
+    else if (equ->bands[i]->type == BAND_TYPE_LOW_SHELF)
+      setup_low_shelf_filter (audioeq, equ->bands[i]);
+    else
+      setup_high_shelf_filter (audioeq, equ->bands[i]);
+  }
+
+  equ->need_new_coefficients = FALSE;
+}
+
+/* Must be called with transform lock! */
+static void
+alloc_history (GstIirEqualizer * equ)
+{
+  GST_DEBUG ("alloc_history");
+  /* free + alloc = no memcpy */
+  g_free (equ->history);
+  equ->history =
+      g_malloc0 (equ->history_size *  equ->audiofilter.format.channels *
+      equ->freq_band_count);
+}
+void
+gst_audioeq_band_set_property(Gstaudioeq * audioeq)
+{
+  GST_DEBUG ("gst_audioeq_band_set_property");
+  GstIirEqualizer *equ = &audioeq->equ;
+  gshort i ;
+  for ( i = 0; i < DEFAULT_CUSTOM_EQ_NUM; i++){
+     GST_DEBUG ("gain = %lf -> %d", equ->bands[i]->gain, audioeq->custom_eq[i] );
+     if (audioeq->custom_eq[i] != equ->bands[i]->gain) {
+        equ->bands[i]->gain = audioeq->custom_eq[i];
+        GST_DEBUG("changed gain = %lf ", equ->bands[i]->gain);
+        g_object_notify (G_OBJECT (equ->bands[i]), "gain");
+     }
+  }
+}
+
+void
+gst_iir_equalizer_compute_frequencies (Gstaudioeq * audioeq, guint new_count)
+{
+  GST_DEBUG ("gst_iir_equalizer_compute_frequencies");
+
+  GstIirEqualizer *equ = &audioeq->equ;
+  guint old_count, i;
+  gdouble freq0, freq1, step;
+  gchar name[20];
+  GST_DEBUG ("gst_iir_equalizer_compute_frequencies before calling equalizer object");
+  if (equ->freq_band_count == new_count)
+    return;
+
+  GST_DEBUG ("gst_iir_equalizer_compute_frequencies equalizer object");
+
+  BANDS_LOCK (equ);
+  GST_DEBUG ("gst_iir_equalizer_compute_frequencies 1");
+  if (G_UNLIKELY (equ->freq_band_count == new_count)) {
+    BANDS_UNLOCK (equ);
+    return;
+  }
+  GST_DEBUG ("gst_iir_equalizer_compute_frequencies 2");
+  old_count = equ->freq_band_count;
+  equ->freq_band_count = new_count;
+  GST_DEBUG ("bands %u -> %u", old_count, new_count);
+
+  if (old_count < new_count) {
+    /* add new bands */
+    equ->bands = g_realloc (equ->bands, sizeof (GstObject *) * new_count);
+    for (i = old_count; i < new_count; i++) {
+      equ->bands[i] = g_object_new (GST_TYPE_IIR_EQUALIZER_BAND, NULL);
+      /* otherwise they get names like 'iirequalizerband5' */
+      snprintf (name, sizeof(name), "band%u", i);
+      gst_object_set_name (GST_OBJECT (equ->bands[i]), name);
+      GST_DEBUG ("adding band[%d]=%p", i, equ->bands[i]);
+
+      gst_object_set_parent (GST_OBJECT (equ->bands[i]), GST_OBJECT (audioeq));
+      gst_child_proxy_child_added (GST_OBJECT (audioeq),
+          GST_OBJECT (equ->bands[i]));
+    }
+  } else {
+    /* free unused bands */
+    for (i = new_count; i < old_count; i++) {
+      GST_DEBUG ("removing band[%d]=%p", i, equ->bands[i]);
+      gst_child_proxy_child_removed (GST_OBJECT (audioeq),
+          GST_OBJECT (equ->bands[i]));
+      gst_object_unparent (GST_OBJECT (equ->bands[i]));
+      equ->bands[i] = NULL;
+    }
+  }
+
+  alloc_history (equ);
+
+  /* set center frequencies and name band objects
+   * FIXME: arg! we can't change the name of parented objects :(
+   *   application should read band->freq to get the name
+   */
+
+  step = pow (HIGHEST_FREQ / LOWEST_FREQ, 1.0 / new_count);
+  freq0 = LOWEST_FREQ;
+  for (i = 0; i < new_count; i++) {
+    freq1 = freq0 * step;
+
+    if (i == 0)
+      equ->bands[i]->type = BAND_TYPE_LOW_SHELF;
+    else if (i == new_count - 1)
+      equ->bands[i]->type = BAND_TYPE_HIGH_SHELF;
+    else
+      equ->bands[i]->type = BAND_TYPE_PEAK;
+
+    equ->bands[i]->freq = freq0 + ((freq1 - freq0) / 2.0);
+    equ->bands[i]->width = freq1 - freq0;
+    GST_DEBUG ("band[%2d] = '%lf'", i, equ->bands[i]->freq);
+
+    g_object_notify (G_OBJECT (equ->bands[i]), "bandwidth");
+    g_object_notify (G_OBJECT (equ->bands[i]), "freq");
+    g_object_notify (G_OBJECT (equ->bands[i]), "type");
+
+    freq0 = freq1;
+  }
+
+  equ->need_new_coefficients = TRUE;
+
+  BANDS_UNLOCK (equ);
+}
+/* start of code that is type specific */
+
+#define CREATE_OPTIMIZED_FUNCTIONS_INT(TYPE,BIG_TYPE,MIN_VAL,MAX_VAL)   \
+typedef struct {                                                        \
+  BIG_TYPE x1, x2;          /* history of input values for a filter */  \
+  BIG_TYPE y1, y2;          /* history of output values for a filter */ \
+} SecondOrderHistory ## TYPE;                                           \
+                                                                        \
+static inline BIG_TYPE                                                  \
+one_step_ ## TYPE (GstIirEqualizerBand *filter,                         \
+    SecondOrderHistory ## TYPE *history, BIG_TYPE input)                \
+{                                                                       \
+  /* calculate output */                                                \
+  BIG_TYPE output = filter->a0 * input +                                \
+      filter->a1 * history->x1 + filter->a2 * history->x2 +             \
+      filter->b1 * history->y1 + filter->b2 * history->y2;              \
+  /* update history */                                                  \
+  history->y2 = history->y1;                                            \
+  history->y1 = output;                                                 \
+  history->x2 = history->x1;                                            \
+  history->x1 = input;                                                  \
+                                                                        \
+  return output;                                                        \
+}                                                                       \
+                                                                        \
+static const guint                                                      \
+history_size_ ## TYPE = sizeof (SecondOrderHistory ## TYPE);            \
+                                                                        \
+static void                                                             \
+gst_iir_equ_process_ ## TYPE (GstIirEqualizer *equ, guint8 *data,       \
+guint size, guint channels)                                             \
+{                                                                       \
+  guint frames = size / channels / sizeof (TYPE);                       \
+  guint i, c, f, nf = equ->freq_band_count;                             \
+  BIG_TYPE cur;                                                         \
+  GstIirEqualizerBand **filters = equ->bands;                           \
+                                                                        \
+  for (i = 0; i < frames; i++) {                                        \
+    SecondOrderHistory ## TYPE *history = equ->history;                 \
+    for (c = 0; c < channels; c++) {                                    \
+      cur = *((TYPE *) data);                                           \
+      for (f = 0; f < nf; f++) {                                        \
+        cur = one_step_ ## TYPE (filters[f], history, cur);             \
+        history++;                                                      \
+      }                                                                 \
+      cur = CLAMP (cur, MIN_VAL, MAX_VAL);                              \
+      *((TYPE *) data) = (TYPE) floor (cur);                            \
+      data += sizeof (TYPE);                                            \
+    }                                                                   \
+  }                                                                     \
+}
+
+#define CREATE_OPTIMIZED_FUNCTIONS(TYPE)                                \
+typedef struct {                                                        \
+  TYPE x1, x2;          /* history of input values for a filter */  \
+  TYPE y1, y2;          /* history of output values for a filter */ \
+} SecondOrderHistory ## TYPE;                                           \
+                                                                        \
+static inline TYPE                                                      \
+one_step_ ## TYPE (GstIirEqualizerBand *filter,                         \
+    SecondOrderHistory ## TYPE *history, TYPE input)                    \
+{                                                                       \
+  /* calculate output */                                                \
+  TYPE output = filter->a0 * input + filter->a1 * history->x1 +         \
+      filter->a2 * history->x2 + filter->b1 * history->y1 +             \
+      filter->b2 * history->y2;                                         \
+  /* update history */                                                  \
+  history->y2 = history->y1;                                            \
+  history->y1 = output;                                                 \
+  history->x2 = history->x1;                                            \
+  history->x1 = input;                                                  \
+                                                                        \
+  return output;                                                        \
+}                                                                       \
+                                                                        \
+static const guint                                                      \
+history_size_ ## TYPE = sizeof (SecondOrderHistory ## TYPE);            \
+                                                                        \
+static void                                                             \
+gst_iir_equ_process_ ## TYPE (GstIirEqualizer *equ, guint8 *data,       \
+guint size, guint channels)                                             \
+{                                                                       \
+  guint frames = size / channels / sizeof (TYPE);                       \
+  guint i, c, f, nf = equ->freq_band_count;                             \
+  TYPE cur;                                                             \
+  GstIirEqualizerBand **filters = equ->bands;                           \
+                                                                        \
+  for (i = 0; i < frames; i++) {                                        \
+    SecondOrderHistory ## TYPE *history = equ->history;                 \
+    for (c = 0; c < channels; c++) {                                    \
+      cur = *((TYPE *) data);                                           \
+      for (f = 0; f < nf; f++) {                                        \
+        cur = one_step_ ## TYPE (filters[f], history, cur);             \
+        history++;                                                      \
+      }                                                                 \
+      *((TYPE *) data) = (TYPE) cur;                                    \
+      data += sizeof (TYPE);                                            \
+    }                                                                   \
+  }                                                                     \
+}
+
+CREATE_OPTIMIZED_FUNCTIONS_INT (gint16, gfloat, -32768.0, 32767.0);
+CREATE_OPTIMIZED_FUNCTIONS (gfloat);
+CREATE_OPTIMIZED_FUNCTIONS (gdouble);
+
+#ifdef AUDIOEQ_REDUCE_MEMCPY
+static GstFlowReturn
+gst_audioeq_transform_ip (GstBaseTransform * base, GstBuffer * buf)
+{
+  GST_DEBUG ("gst_audioeq_transform_ip");
+  Gstaudioeq *audioeq = GST_AUDIOEQ(base);
+  GstIirEqualizer *equ = &audioeq->equ;
+
+  equ->history_size = history_size_gint16;
+  equ->process = gst_iir_equ_process_gint16;
+   g_free (equ->history);
+  equ->history = g_malloc0 (equ->history_size *  audioeq->channels * equ->freq_band_count);
+  GstClockTime timestamp;
+
+  if (G_UNLIKELY (audioeq->channels < 1 || equ->process == NULL)) {
+    GST_DEBUG ("gst_audioeq_transform_ip return GST_FLOW_NOT_NEGOTIATED;");
+    if (G_UNLIKELY (equ->process == NULL))
+    GST_DEBUG ("gst_audioeq_transform_ip equ->process ");
+    if (G_UNLIKELY (audioeq->channels < 1))
+    GST_DEBUG ("gst_audioeq_transform_ip audioeq->channels");
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+      GST_DEBUG ("gst_audioeq_transform_ip  BANDS_LOCK (equ);");
+  BANDS_LOCK (equ);
+  if (equ->need_new_coefficients) {
+    GST_DEBUG ("gst_audioeq_transform_ip  update_coefficients");
+    update_coefficients (audioeq);
+    set_passthrough (audioeq);
+  }
+  BANDS_UNLOCK (equ);
+
+  if (gst_base_transform_is_passthrough (base)) {
+    GST_DEBUG ("gst_audioeq_transform_ip gst_base_transform_is_passthrough return GST_FLOW_OK;");
+    return GST_FLOW_OK;
+  }
+  timestamp = GST_BUFFER_TIMESTAMP (buf);
+  timestamp =
+      gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
+
+  if (GST_CLOCK_TIME_IS_VALID (timestamp))
+    gst_object_sync_values (G_OBJECT (audioeq), timestamp);
+  GST_DEBUG ("  equ->process ++");
+  equ->process (equ, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
+      audioeq->channels);
+  GST_DEBUG ("  equ->process --");
+  GST_DEBUG ("gst_audioeq_transform_ip return GST_FLOW_OK;");
+  return GST_FLOW_OK;
+}
+#endif
+
+static gboolean
+gst_audioeq_set_caps (GstBaseTransform * base, GstCaps * incaps,
+       GstCaps * outcaps)
+{
+  GST_DEBUG ("gst_audioeq_set_caps");
+       Gstaudioeq *audioeq = GST_AUDIOEQ(base);
+       GstStructure *ins;
+       GstPad *pad;
+       gint samplerate;
+       gint channels;
+       gshort old_samplerate;
+       gshort old_channels;
+
+       pad = gst_element_get_static_pad(GST_ELEMENT(audioeq), "src");
+
+       /* forward-negotiate */
+       if(!gst_pad_set_caps(pad, incaps)) {
+               gst_object_unref(pad);
+               return FALSE;
+       }
+
+       /* negotiation succeeded, so now configure ourselves */
+       ins = gst_caps_get_structure(incaps, 0);
+
+       /* get samplerate from caps & convert */
+       old_samplerate = audioeq->samplerate;
+       old_channels = audioeq->channels;
+       gst_structure_get_int(ins, "rate", &samplerate);
+       switch (samplerate) {
+       case 48000:
+               audioeq->samplerate = SAMPLERATE_48000Hz;
+               break;
+       case 44100:
+               audioeq->samplerate = SAMPLERATE_44100Hz;
+               break;
+       case 32000:
+               audioeq->samplerate = SAMPLERATE_32000Hz;
+               break;
+       case 24000:
+               audioeq->samplerate = SAMPLERATE_24000Hz;
+               break;
+       case 22050:
+               audioeq->samplerate = SAMPLERATE_22050Hz;
+               break;
+       case 16000:
+               audioeq->samplerate = SAMPLERATE_16000Hz;
+               break;
+       case 12000:
+               audioeq->samplerate = SAMPLERATE_12000Hz;
+               break;
+       case 11025:
+               audioeq->samplerate = SAMPLERATE_11025Hz;
+               break;
+       case 8000:
+               audioeq->samplerate = SAMPLERATE_8000Hz;
+               break;
+       default:
+               if (samplerate < 8000) {
+                       audioeq->samplerate = SAMPLERATE_8000Hz;
+               } else if (samplerate > 48000) {
+                       audioeq->samplerate = SAMPLERATE_48000Hz;
+               }
+               break;
+       }
+       /* get number of channels from caps */
+       gst_structure_get_int(ins, "channels", &channels);
+       audioeq->channels = (gshort)channels;
+
+       if ((old_samplerate != audioeq->samplerate)
+               || (old_channels != audioeq->channels)) {
+               audioeq->need_update_filter = TRUE;
+       }
+
+       gst_object_unref (pad);
+
+       return TRUE;
+}
+
+static void
+gst_audioeq_set_property (GObject * object, guint prop_id,
+       const GValue * value, GParamSpec * pspec)
+{
+       GST_DEBUG ("gst_audioeq_set_property");
+       Gstaudioeq *audioeq = GST_AUDIOEQ (object);
+       GstIirEqualizer *equ = &audioeq->equ;
+       gshort *pointer;
+
+       switch (prop_id) {
+
+       case PROP_FILTER_ACTION:
+               audioeq->filter_action = g_value_get_uint(value);
+               BANDS_LOCK(equ);
+               equ->need_new_coefficients = TRUE;
+               BANDS_UNLOCK(equ);
+               break;
+
+       case PROP_CUSTOM_EQ:
+               pointer = g_value_get_pointer(value);
+               if (pointer) {
+                       memcpy(audioeq->custom_eq, pointer, sizeof(gint) * CUSTOM_EQ_BAND_MAX);
+                       if (audioeq->filter_action == FILTER_ADVANCED_SETTING) {
+                               BANDS_LOCK(equ);
+                               equ->need_new_coefficients = TRUE;
+                               gst_audioeq_band_set_property(audioeq);
+                               BANDS_UNLOCK(equ);
+                       }
+               }
+               break;
+
+       default:
+               break;
+       }
+       GST_DEBUG ("gst_audioeq_set_property need_update_filter %d", audioeq->need_update_filter);
+}
+
+static void
+gst_audioeq_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
+{
+GST_DEBUG ("gst_audioeq_get_property");
+
+       Gstaudioeq *audioeq = GST_AUDIOEQ (object);
+       GstIirEqualizer *equ = &audioeq->equ;
+       gshort i;
+       gdouble widtharr[DEFAULT_CUSTOM_EQ_NUM],freqarr[DEFAULT_CUSTOM_EQ_NUM];
+
+       switch (prop_id) {
+       case PROP_FILTER_ACTION:
+               g_value_set_uint(value, audioeq->filter_action);
+               break;
+
+       case PROP_CUSTOM_EQ:
+               g_value_set_pointer(value, audioeq->custom_eq);
+               break;
+
+       case PROP_CUSTOM_EQ_NUM:
+               g_value_set_uint(value, DEFAULT_CUSTOM_EQ_NUM);
+               break;
+
+       case PROP_CUSTOM_EQ_FREQ:
+               for(i=0;i<DEFAULT_CUSTOM_EQ_NUM;i++) {
+                        freqarr[i] =   equ->bands[i]->freq;
+               }
+               g_value_set_pointer(value, &freqarr);
+               break;
+
+       case PROP_CUSTOM_EQ_WIDTH:
+               for(i=0;i<DEFAULT_CUSTOM_EQ_NUM;i++) {
+                        widtharr[i] =  equ->bands[i]->width;
+               }
+               g_value_set_pointer(value, &widtharr);
+               break;
+
+       default:
+               break;
+       }
+}
+
+static gboolean
+gst_iir_equalizer_setup (GstAudioFilter * audio, GstRingBufferSpec * fmt)
+{
+GST_DEBUG ("gst_iir_equalizer_setup");
+  GstIirEqualizer *equ = GST_IIR_EQUALIZER (audio);
+
+  switch (fmt->type) {
+    case GST_BUFTYPE_LINEAR:
+      switch (fmt->width) {
+        case 16:
+          equ->history_size = history_size_gint16;
+          equ->process = gst_iir_equ_process_gint16;
+          break;
+        default:
+          return FALSE;
+      }
+      break;
+    case GST_BUFTYPE_FLOAT:
+      switch (fmt->width) {
+        case 32:
+          equ->history_size = history_size_gfloat;
+          equ->process = gst_iir_equ_process_gfloat;
+          break;
+        case 64:
+          equ->history_size = history_size_gdouble;
+          equ->process = gst_iir_equ_process_gdouble;
+          break;
+        default:
+          return FALSE;
+      }
+      break;
+    default:
+      return FALSE;
+  }
+
+  alloc_history (equ);
+  return TRUE;
+}
+
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+       GST_DEBUG ("audioeq plugin_init ");
+       GST_DEBUG_CATEGORY_INIT(gst_audioeq_debug, "audioeq", 0, "Audio Equalizer Plugin");
+       return gst_element_register(plugin, "audioeq", GST_RANK_NONE, GST_TYPE_AUDIOEQ);
+}
+
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+       GST_VERSION_MINOR,
+       "audioeq",
+       "Audio Equalizer Plugin",
+       plugin_init,
+       VERSION,
+       "LGPL",
+       "gst-plugins-ext",
+       "https://www.tizen.org/")
diff --git a/audioeq/src/gstaudioeq.h b/audioeq/src/gstaudioeq.h
new file mode 100644 (file)
index 0000000..a2c3815
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * audioeq
+ *
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Aditi Narula <aditi.n@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_AUDIOEQ_H__
+#define __GST_AUDIOEQ_H__
+
+#include <stdio.h>
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/audio/gstringbuffer.h>
+#include <gst/controller/gstcontroller.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIOEQ \
+       (gst_audioeq_get_type())
+#define GST_AUDIOEQ(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIOEQ,Gstaudioeq))
+#define GST_audioeq_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIOEQ,GstaudioeqClass))
+#define GST_IS_AUDIOEQ(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIOEQ))
+#define GST_IS_AUDIOEQ_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIOEQ))
+#define GST_TYPE_IIR_EQUALIZER \
+  (gst_iir_equalizer_get_type())
+#define GST_IIR_EQUALIZER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IIR_EQUALIZER,GstIirEqualizer))
+#define GST_IIR_EQUALIZER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IIR_EQUALIZER,GstIirEqualizerClass))
+#define GST_IS_IIR_EQUALIZER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IIR_EQUALIZER))
+#define GST_IS_IIR_EQUALIZER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IIR_EQUALIZER))
+
+typedef struct _Gstaudioeq Gstaudioeq;
+typedef struct _GstaudioeqClass GstaudioeqClass;
+typedef struct _GstIirEqualizer GstIirEqualizer;
+typedef struct _GstIirEqualizerClass GstIirEqualizerClass;
+typedef struct _GstIirEqualizerBand GstIirEqualizerBand;
+
+#define CUSTOM_EQ_BAND_MAX                             9
+
+#define LOWEST_FREQ (20.0)
+#define HIGHEST_FREQ (20000.0)
+
+typedef void (*ProcessFunc) (GstIirEqualizer * eq, guint8 * data, guint size,
+    guint channels);
+
+struct _GstIirEqualizer
+{
+  GstAudioFilter audiofilter;
+
+  /*< private >*/
+
+  GMutex *bands_lock;
+  GstIirEqualizerBand **bands;
+
+  /* properties */
+  guint freq_band_count;
+  /* for each band and channel */
+  gpointer history;
+  guint history_size;
+
+  gboolean need_new_coefficients;
+
+  ProcessFunc process;
+};
+
+struct _GstIirEqualizerClass
+{
+  GstAudioFilterClass audiofilter_class;
+};
+
+
+
+struct _Gstaudioeq
+{
+       GstBaseTransform element;
+
+       guint           samplerate;
+       guint           channels;
+
+       /* properties */
+       guint           filter_action;
+       gint                    custom_eq[CUSTOM_EQ_BAND_MAX];
+       gboolean                need_update_filter;
+       GstIirEqualizer equ;
+};
+
+struct _GstaudioeqClass
+{
+       GstAudioFilterClass parent_class;
+};
+
+void gst_iir_equalizer_compute_frequencies (Gstaudioeq * audioeq, guint new_count);
+
+GType gst_iir_equalizer_get_type(void);
+
+GType gst_audioeq_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIOEQ_H__ */
+
index 5b1419b..f0e73e4 100755 (executable)
@@ -517,6 +517,7 @@ send_reverse:
     return GST_FLOW_OK;
   }
 
+#if 0
 send_dummy:
   {
 
@@ -532,6 +533,7 @@ send_dummy:
     }
     return GST_FLOW_OK;
   }
+#endif
 
 error_exit:
 
diff --git a/avsystem/src/Makefile.am b/avsystem/src/Makefile.am
deleted file mode 100644 (file)
index dd1576e..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-
-# plugindir is set in configure
-
-plugin_LTLIBRARIES = libgstavsysaudiosrc.la
-
-# sources used to compile this plug-in
-libgstavsysaudiosrc_la_SOURCES = gstavsyssrc.c \
-                                 gstavsysaudiosrc.c
-
-libgstavsysaudiosrc_la_CFLAGS = $(GST_CFLAGS) \
-                           $(GST_BASE_CFLAGS) \
-                           $(AVSYSTEM_CFLAGS) \
-                           $(GST_VIDEO_FLAGS) \
-                           -I$(includedir)/mmf \
-                           $(MMTA_CFLAGS) \
-                           $(GST_AUDIO_CFLAGS) \
-                           $(VCONF_CFLAGS) \
-                           $(AVSYSAUDIO_CFLAGS)
-
-libgstavsysaudiosrc_la_LIBADD = $(GST_LIBS) \
-                           $(GST_BASE_LIBS) \
-                           $(DATACOMLIB_LIBS) \
-                           $(HTTPLIB_LIBS) \
-                           $(AVSYSTEM_LIBS) \
-                           $(GST_VIDEO_LIBS) \
-                           -lgstaudio-0.10 \
-                           $(MMTA_LIBS) \
-                           $(GST_AUDIO_LIBS) \
-                           -ldl \
-                           $(VCONF_LIBS) \
-                           $(AVSYSAUDIO_LIBS)
-
-libgstavsysaudiosrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-
-if IS_I386
-libgstavsysaudiosrc_la_CFLAGS += -DI386_SIMULATOR
-else
-endif
-
-plugin_LTLIBRARIES += libgstavsyssink.la
-
-## sources used to compile this plug-in
-libgstavsyssink_la_SOURCES = gstavsyssink.c \
-                        gstavsysmemsink.c
-
-libgstavsyssink_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(AVSYSVIDEO_CFLAGS) $(AVSYSTEM_CFLAGS) -I$(includedir)/mmf
-libgstavsyssink_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(DATACOMLIB_LIBS) $(HTTPLIB_LIBS) $(AVSYSVIDEO_LIBS) $(AVSYSTEM_LIBS) $(GST_VIDEO_LIBS) -lgstaudio-0.10 -ldl
-libgstavsyssink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-
-
-libgstavsyssink_la_SOURCES += gstavsysaudiosink.c
-libgstavsyssink_la_CFLAGS  += $(AVSYSAUDIO_CFLAGS)
-libgstavsyssink_la_LIBADD  += $(AVSYSAUDIO_LIBS)
-
-if IS_I386
-libgstavsyssink_la_CFLAGS += -DI386_SIMULATOR
-else
-endif
-
-
diff --git a/avsystem/src/gstavsysaudiosink.c b/avsystem/src/gstavsysaudiosink.c
deleted file mode 100644 (file)
index 3a6f224..0000000
+++ /dev/null
@@ -1,943 +0,0 @@
-/*
- * avsystem
- *
- * 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
- *
- */
-
-
-
-#include <gst/gst.h>
-#include <gst/gstutils.h>
-
-#include <string.h>
-
-#include "gstavsysaudiosink.h"
-
-#define _ALSA_DAPM_
-#define __REPLACE_RESET_WITH_CLOSE_AND_REOPEN__
-
-#define CONVERT_MUTE_VALUE(_mute) ((_mute) ? AVSYS_AUDIO_MUTE : AVSYS_AUDIO_UNMUTE)
-
-GST_DEBUG_CATEGORY_EXTERN (avsystem_sink_debug);
-#define GST_CAT_DEFAULT avsystem_sink_debug
-
-#define DEFAULT_USER_ROUTE     AVSYSAUDIOSINK_USERROUTE_AUTO
-#define DEFAULT_AUDIO_ROUTE    AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING
-#define DEFAULT_VOLUME_TYPE            AVSYS_AUDIO_VOLUME_TYPE_MEDIA
-#define DEFAULT_MEDIACALL_MODE AVSYS_AUDIO_ECHO_MODE_NONE
-#define DEFAULT_FADEUP_VOLUME  FALSE
-#define DEFAULT_AUDIO_MUTE     AVSYSAUDIOSINK_AUDIO_UNMUTE
-#define DEFAULT_AUDIO_LATENCY  AVSYSAUDIOSINK_LATENCY_MID
-
-
-//GST_DEBUG_CATEGORY_STATIC (gst_avsystemsink_debug);
-
-/* element factory information */
-static const GstElementDetails gst_avsysaudiosink_details =
-    GST_ELEMENT_DETAILS ("AV-system Audio OUT",
-                         "Sink/Audio",
-                         "Output to AV System",
-                         "Samsung Electronics co., ltd");
-
-enum
-{
-    PROP_0,
-    PROP_AUDIO_MUTE,
-    PROP_AUDIO_VOLUME_TYPE,
-    PROP_AUDIO_PRIORITY,
-    PROP_AUDIO_FADEUPVOLUME,
-    PROP_AUDIO_ROUTE_POLICY,
-    PROP_AUDIO_USER_ROUTE,
-    PROP_AUDIO_LATENCY,
-    PROP_AUDIO_HANDLE,
-    PROP_AUDIO_CALLBACK
-};
-
-GType
-gst_avsysaudiosink_audio_mute_get_type (void)
-{
-  static GType avaudio_mute_type = 0;
-  static const GEnumValue avaudio_mute[] = {
-    {AVSYSAUDIOSINK_AUDIO_UNMUTE, "Unmute", "unmute"},
-    {AVSYSAUDIOSINK_AUDIO_MUTE, "Mute immediately", "mute"},
-    {AVSYSAUDIOSINK_AUDIO_MUTE_WITH_FADEDOWN_EFFECT, "Mute with fadedown effect", "fadedown"},
-    {0, NULL, NULL},
-  };
-
-  if (!avaudio_mute_type) {
-         avaudio_mute_type =
-        g_enum_register_static ("GstAvsysAudioSinkAudioMute", avaudio_mute);
-  }
-  return avaudio_mute_type;
-}
-
-GType
-gst_avsysaudiosink_user_route_get_type (void)
-{
-       static GType user_route_type = 0;
-       static const GEnumValue user_route[] = {
-               {AVSYSAUDIOSINK_USERROUTE_AUTO, "Route automatically", "auto"},
-               {AVSYSAUDIOSINK_USERROUTE_PHONE, "Route to phone only", "phone"},
-                 {0, NULL, NULL},
-       };
-
-       if (!user_route_type) {
-               user_route_type =
-                               g_enum_register_static ("GstAvsysAudioSinkUserRoutePolicy",user_route);
-       }
-       return user_route_type;
-}
-
-GType
-gst_avsysaudiosink_audio_route_get_type (void)
-{
-  static GType playback_audio_route_type = 0;
-  static const GEnumValue playback_audio_route[] = {
-    {AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING, "Use external sound path", "external"},
-    {AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_NORMAL, "Auto change between speaker & earphone", "normal"},
-    {AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_ALERT, "Play via both speaker & earphone", "alert"},
-    {AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_HEADSET_ONLY, "Play via earphone only", "headset"},
-    {0, NULL, NULL},
-  };
-
-  if (!playback_audio_route_type) {
-         playback_audio_route_type =
-        g_enum_register_static ("GstAvsysAudioSinkAudioRoutePolicy", playback_audio_route);
-  }
-  return playback_audio_route_type;
-}
-
-
-GType
-gst_avsysaudiosink_volume_table_get_type (void)
-{
-  static GType avsysaudio_volume_table_type = 0;
-  static const GEnumValue avsysaudio_volume_table[] = {
-    {AVSYS_AUDIO_VOLUME_TYPE_SYSTEM, "System Volume", "system"},
-    {AVSYS_AUDIO_VOLUME_TYPE_NOTIFICATION, "Notification Volume", "notification"},
-    {AVSYS_AUDIO_VOLUME_TYPE_ALARM, "Alarm Volume", "alarm"},
-    {AVSYS_AUDIO_VOLUME_TYPE_RINGTONE, "Ringtone Volume", "ringtone"},
-    {AVSYS_AUDIO_VOLUME_TYPE_MEDIA, "Media Volume", "media"},
-    {AVSYS_AUDIO_VOLUME_TYPE_CALL, "Call Volume", "call"},
-    {AVSYS_AUDIO_VOLUME_TYPE_FIXED, "Fixed Volume", "fixed"},
-    {AVSYS_AUDIO_VOLUME_TYPE_EXT_SYSTEM_JAVA, "Java Volume", "java"},
-    {0, NULL, NULL},
-  };
-
-  if (!avsysaudio_volume_table_type) {
-         avsysaudio_volume_table_type =
-        g_enum_register_static ("GstAvsysAudioSinkVolumeTable", avsysaudio_volume_table);
-  }
-  return avsysaudio_volume_table_type;
-}
-
-GType
-gst_avsysaudiosink_latency_get_type (void)
-{
-  static GType avsysaudio_latency_type = 0;
-  static const GEnumValue avsysaudio_latency[] = {
-    {AVSYSAUDIOSINK_LATENCY_LOW, "Low latency", "low"},
-    {AVSYSAUDIOSINK_LATENCY_MID, "Mid latency", "mid"},
-    {AVSYSAUDIOSINK_LATENCY_HIGH, "High latency", "high"},
-    {0, NULL, NULL},
-  };
-
-  if (!avsysaudio_latency_type) {
-         avsysaudio_latency_type =
-        g_enum_register_static ("GstAvsysAudioSinkLatency", avsysaudio_latency);
-  }
-  return avsysaudio_latency_type;
-}
-
-static void gst_avsysaudiosink_init_interfaces (GType type);
-
-//#define GST_BOILERPLATE_FULL(type, type_as_function, parent_type, parent_type_macro, additional_initializations)
-
-GST_BOILERPLATE_FULL (GstAvsysAudioSink, gst_avsysaudiosink, GstAudioSink,
-                                         GST_TYPE_AUDIO_SINK, gst_avsysaudiosink_init_interfaces);
-
-
-static void gst_avsysaudiosink_finalise (GObject * object);
-static void gst_avsysaudiosink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_avsysaudiosink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
-#if 0  /*not use*/
-static GstCaps *gst_avsysaudiosink_getcaps (GstBaseSink * bsink);
-#endif
-
-static gboolean gst_avsysaudiosink_avsys_close(GstAvsysAudioSink *avsys_audio);
-static gboolean gst_avsysaudiosink_avsys_open(GstAvsysAudioSink *avsys_audio);
-
-static gboolean gst_avsysaudiosink_open (GstAudioSink * asink);
-static gboolean gst_avsysaudiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec);
-static gboolean gst_avsysaudiosink_unprepare (GstAudioSink * asink);
-static gboolean gst_avsysaudiosink_close (GstAudioSink * asink);
-static guint gst_avsysaudiosink_write (GstAudioSink * asink, gpointer data, guint length);
-static guint gst_avsysaudiosink_delay (GstAudioSink * asink);
-static void gst_avsysaudiosink_reset (GstAudioSink * asink);
-static gboolean avsysaudiosink_post_message(GstAvsysAudioSink* self,int errorcode);
-
-
-#define AVSYS_AUDIO_FACTORY_ENDIANNESS "LITTLE_ENDIAN"
-
-
-static GstStaticPadTemplate avsysaudiosink_sink_factory =
-       GST_STATIC_PAD_TEMPLATE ("sink",
-                                                        GST_PAD_SINK,
-                                                        GST_PAD_ALWAYS,
-                                                        GST_STATIC_CAPS ("audio/x-raw-int, "
-                                                                        "endianness = (int) { " AVSYS_AUDIO_FACTORY_ENDIANNESS " }, "
-                                                                        "signed = (boolean) { TRUE }, "
-                                                                        "width = (int) 16, "
-                                                                        "depth = (int) 16, "
-                                                                        "rate = (int) [ 1, MAX ], "
-                                                                        "channels = (int) [ 1, 2 ]; "
-                                                                        "audio/x-raw-int, "
-                                                                        "signed = (boolean) { FALSE }, "
-                                                                        "width = (int) 8, "
-                                                                        "depth = (int) 8, "
-                                                                        "rate = (int) [ 1, MAX ], "
-                                                                        "channels = (int) [ 1, 2 ] "
-                                                                )
-                                                        );
-/*
-static inline guint _time_to_sample(GstAvsysAudioSink * asink,  GstClockTime diff)
-{
-       guint result = 0;
-       result =(GST_TIME_AS_USECONDS(diff) * asink->audio_param.samplerate)/1000000;
-       return result;
-}
-*/
-
-static void
-gst_avsysaudiosink_finalise (GObject * object)
-{
-    GstAvsysAudioSink *sink = NULL;
-
-    sink = GST_AVSYS_AUDIO_SINK (object);
-    gst_avsysaudiosink_avsys_close(sink);
-    g_mutex_free (sink->avsys_audio_lock);
-    g_mutex_free (sink->avsys_audio_reset_lock);
-
-    G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_avsysaudiosink_init_interfaces (GType type)
-{
-       /* None */
-}
-
-static void
-gst_avsysaudiosink_base_init (gpointer g_class)
-{
-    GstElementClass *element_class = NULL;
-
-    element_class = GST_ELEMENT_CLASS (g_class);
-    gst_element_class_set_details (element_class, &gst_avsysaudiosink_details);
-    gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&avsysaudiosink_sink_factory));
-}
-
-static GstStateChangeReturn
-gst_avsyssudiosink_change_state (GstElement *element, GstStateChange transition);
-
-
-static void
-gst_avsysaudiosink_class_init (GstAvsysAudioSinkClass * klass)
-{
-    GObjectClass *gobject_class;
-    GstElementClass *gstelement_class;
-    GstBaseSinkClass *gstbasesink_class;
-    GstBaseAudioSinkClass *gstbaseaudiosink_class;
-    GstAudioSinkClass *gstaudiosink_class;
-
-    gobject_class = (GObjectClass *) klass;
-    gstelement_class = (GstElementClass *) klass;
-    gstbasesink_class = (GstBaseSinkClass *) klass;
-    gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
-    gstaudiosink_class = (GstAudioSinkClass *) klass;
-
-    parent_class = g_type_class_peek_parent (klass);
-    gstelement_class->change_state  = GST_DEBUG_FUNCPTR(gst_avsyssudiosink_change_state);
-
-    gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_finalise);
-    gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_get_property);
-    gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_set_property);
-
-//     gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_getcaps);
-
-    gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_open);
-    gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_prepare);
-    gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_unprepare);
-    gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_close);
-    gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_write);
-    gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_delay);
-    gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_avsysaudiosink_reset);
-
-       g_object_class_install_property (  gobject_class, PROP_AUDIO_VOLUME_TYPE,
-                       g_param_spec_enum ("volumetype", "Avsystem Volume Type",
-                                       "Select avsystem audio software volume type",
-                                       GST_AVSYS_AUDIO_SINK_VOLUME_TYPE, DEFAULT_VOLUME_TYPE,
-                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-       g_object_class_install_property (  gobject_class, PROP_AUDIO_PRIORITY,
-                       g_param_spec_int ("priority", "Avsystem Sound Priority", "Avsystem sound priority",
-                                       AVSYS_AUDIO_PRIORITY_NORMAL, AVSYS_AUDIO_PRIORITY_SOLO_WITH_TRANSITION_EFFECT,
-                                       AVSYS_AUDIO_PRIORITY_NORMAL, G_PARAM_READWRITE));
-
-       g_object_class_install_property (  gobject_class, PROP_AUDIO_HANDLE,
-                       g_param_spec_pointer("audio-handle", "Avsystem handle",
-                                       "Avsystem audio handle", 
-                                       G_PARAM_READWRITE));
-
-       g_object_class_install_property (  gobject_class, PROP_AUDIO_CALLBACK,
-                       g_param_spec_pointer("audio-callback", "Avsystem callback",
-                                       "Avsystem audio callback", 
-                                       G_PARAM_READWRITE));
-
-       g_object_class_install_property (gobject_class, PROP_AUDIO_FADEUPVOLUME,
-                       g_param_spec_boolean ("fadeup", "Avsystem fadeup volume",
-                                       "Enable avsystem audio fadeup volume when pause to play",
-                                       DEFAULT_FADEUP_VOLUME, G_PARAM_READWRITE));
-
-       g_object_class_install_property (gobject_class ,PROP_AUDIO_MUTE,
-                       g_param_spec_enum("mute", "Avsystem mute",
-                                       "Avsystem audio mute",
-                                       GST_AVSYS_AUDIO_SINK_MUTE, DEFAULT_AUDIO_MUTE,
-                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
-
-       g_object_class_install_property (gobject_class ,PROP_AUDIO_ROUTE_POLICY,
-                       g_param_spec_enum("audio-route", "Audio Route Policy",
-                                       "Audio route policy of system",
-                                       GST_AVSYS_AUDIO_SINK_AUDIO_ROUTE, DEFAULT_AUDIO_ROUTE,
-                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
-       
-       g_object_class_install_property (gobject_class ,PROP_AUDIO_USER_ROUTE,
-                       g_param_spec_enum("user-route", "User Route Policy",
-                                       "User route policy",
-                                       GST_AVSYS_AUDIO_SINK_USER_ROUTE, DEFAULT_USER_ROUTE,
-                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
-
-       g_object_class_install_property (gobject_class ,PROP_AUDIO_LATENCY,
-                       g_param_spec_enum("latency", "Audio Backend Latency",
-                                       "Audio backend latency",
-                                       GST_AVSYS_AUDIO_SINK_LATENCY_TYPE, DEFAULT_AUDIO_LATENCY,
-                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
-}
-
-static void
-gst_avsysaudiosink_set_property (GObject * object, guint prop_id,
-                                                        const GValue * value, GParamSpec * pspec)
-{
-    GstAvsysAudioSink *sink = NULL;
-    int nvalue = 0;
-    gboolean nbool = FALSE;
-
-    sink = GST_AVSYS_AUDIO_SINK (object);
-
-    switch (prop_id)
-    {
-    case PROP_AUDIO_HANDLE:
-               sink->cbHandle = g_value_get_pointer(value);
-               break;
-    case PROP_AUDIO_CALLBACK:
-               sink->audio_stream_cb = g_value_get_pointer(value);
-               break;
-       
-       case PROP_AUDIO_VOLUME_TYPE:
-           nvalue = g_value_get_enum(value);
-           sink->volume_type = nvalue;
-       break;
-
-    case PROP_AUDIO_PRIORITY:
-               nvalue = g_value_get_int(value);
-       sink->sound_priority = nvalue;
-       break;
-
-    case PROP_AUDIO_MUTE:
-       nvalue = g_value_get_enum(value);
-        if(sink->audio_handle != (avsys_handle_t)-1)
-        {
-            if(AVSYS_SUCCESS(avsys_audio_set_mute_fadedown(sink->audio_handle)))
-                sink->mute = nvalue;
-        }
-        else
-        {
-            sink->mute = nvalue;
-        }
-        break;
-    case PROP_AUDIO_FADEUPVOLUME:
-       nbool = g_value_get_boolean(value);
-       sink->use_fadeup_volume = nbool;
-       break;
-
-    case PROP_AUDIO_ROUTE_POLICY:
-       nvalue = g_value_get_enum(value);
-       sink->audio_route_policy = nvalue;
-               switch(sink->audio_route_policy)
-               {
-               case AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING:
-                       GST_INFO_OBJECT(sink, "use external audio route setting");
-                       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);
-                       break;
-               }
-       break;
-       case PROP_AUDIO_USER_ROUTE:
-               nvalue = g_value_get_enum(value);
-               sink->user_route_policy = nvalue;                       
-               break;
-       case PROP_AUDIO_LATENCY:
-               nvalue = g_value_get_enum(value);
-               sink->latency = nvalue;
-               break;
-       default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-               break;
-       }
-}
-
-static void
-gst_avsysaudiosink_get_property (GObject * object, guint prop_id,
-                                                        GValue * value, GParamSpec * pspec)
-{
-    GstAvsysAudioSink *sink = NULL;
-
-    sink = GST_AVSYS_AUDIO_SINK (object);
-
-    switch (prop_id) {
-       case PROP_AUDIO_VOLUME_TYPE:
-       g_value_set_enum(value, sink->volume_type);
-       break;
-    case PROP_AUDIO_PRIORITY:
-       g_value_set_int(value, sink->sound_priority);
-       break;
-    case PROP_AUDIO_MUTE:
-       g_value_set_enum(value, sink->mute);
-        break;
-    case PROP_AUDIO_FADEUPVOLUME:
-       g_value_set_boolean(value, sink->use_fadeup_volume);
-       break;
-
-    case PROP_AUDIO_ROUTE_POLICY:
-       g_value_set_enum(value, sink->audio_route_policy);
-       break;
-       case PROP_AUDIO_USER_ROUTE:
-               g_value_set_enum(value, sink->user_route_policy);
-               break;
-       case PROP_AUDIO_LATENCY:
-               g_value_set_enum(value, sink->latency);
-               break;
-
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-        break;
-    }
-}
-
-static void
-gst_avsysaudiosink_init (GstAvsysAudioSink * avsysaudiosink, GstAvsysAudioSinkClass * g_class)
-{
-       GST_DEBUG_OBJECT (avsysaudiosink, "initializing avsysaudiosink");
-
-       avsysaudiosink->audio_handle = (avsys_handle_t)-1;
-       avsysaudiosink->cached_caps = NULL;
-       avsysaudiosink->avsys_audio_lock = g_mutex_new ();
-       avsysaudiosink->avsys_audio_reset_lock = g_mutex_new ();
-       avsysaudiosink->volume_type = DEFAULT_VOLUME_TYPE;
-       avsysaudiosink->sound_priority = AVSYS_AUDIO_PRIORITY_NORMAL;
-       avsysaudiosink->mute = DEFAULT_AUDIO_MUTE;
-       avsysaudiosink->use_fadeup_volume = DEFAULT_FADEUP_VOLUME;
-       avsysaudiosink->latency = DEFAULT_AUDIO_LATENCY;
-       avsysaudiosink->audio_route_policy = DEFAULT_AUDIO_ROUTE;
-       avsysaudiosink->bytes_per_sample = 1;
-#if defined (LPCM_DUMP_SUPPORT)
-       avsysaudiosink->dumpFp = NULL;
-#endif
-
-}
-#if 0
-static GstCaps *
-gst_avsysaudiosink_getcaps (GstBaseSink * bsink)
-{
-    GstElementClass *element_class = NULL;
-    GstPadTemplate *pad_template = NULL;
-    GstAvsysAudioSink *sink = GST_AVSYS_AUDIO_SINK (bsink);
-    GstCaps *caps;
-
-//    debug_fenter();
-
-    sink = GST_AVSYS_AUDIO_SINK (bsink);
-    if (sink->audio_handle == -1)
-    {
-        GST_DEBUG_OBJECT (sink, "avsystem audio not open, using template caps");
-        return NULL;              /* base class will get template caps for us */
-    }
-
-    if (sink->cached_caps)
-    {
-        GST_LOG_OBJECT (sink, "Returning cached caps");
-        return gst_caps_ref (sink->cached_caps);
-    }
-
-    element_class = GST_ELEMENT_GET_CLASS (sink);
-    pad_template = gst_element_class_get_pad_template (element_class, "sink");
-    g_return_val_if_fail (pad_template != NULL, NULL);
-
-       // todo : get supported format.
-       //caps = gst_avsysaudio_probe_supported_formats (GST_OBJECT (sink), sink->,
-       //gst_pad_template_get_caps (pad_template));
-
-       //if (caps) {
-       //sink->cached_caps = gst_caps_ref (caps);
-       //}
-
-    GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
-
-    return caps;
-}
-#endif
-
-static gboolean
-avsysaudiosink_parse_spec (GstAvsysAudioSink * avsys_audio, GstRingBufferSpec * spec)
-{
-    /* Check param */
-    if (spec->type != GST_BUFTYPE_LINEAR ||
-        spec->channels > 2 || spec->channels < 1 ||
-        !(spec->format == GST_S8 || spec->format == GST_S16_LE) )
-        return FALSE;
-
-    switch(spec->format)
-    {
-    case GST_S8:
-        avsys_audio->audio_param.format = AVSYS_AUDIO_FORMAT_8BIT;
-        avsys_audio->bytes_per_sample = 1;
-        break;
-    case GST_S16_LE:
-        avsys_audio->audio_param.format = AVSYS_AUDIO_FORMAT_16BIT;
-        avsys_audio->bytes_per_sample = 2;
-        break;
-    default:
-        return FALSE;
-    }
-
-    /// set audio parameter for avsys audio open
-       switch(avsys_audio->latency)
-       {
-       case AVSYSAUDIOSINK_LATENCY_LOW:
-               avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT_VIDEO;
-               break;
-       case AVSYSAUDIOSINK_LATENCY_MID:
-               avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT;
-               break;
-       case AVSYSAUDIOSINK_LATENCY_HIGH:
-               avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_OUTPUT_CLOCK;
-               break;
-       }
-
-
-
-    avsys_audio->audio_param.priority = 0;
-    avsys_audio->audio_param.samplerate = spec->rate;
-    avsys_audio->audio_param.channels = spec->channels;
-
-    if(spec->channels == 2)
-       avsys_audio->bytes_per_sample *= 2;
-    else if(spec->channels > 2)
-    {
-       GST_ERROR_OBJECT(avsys_audio,"Unsupported channel number %d", spec->channels);
-       return FALSE;
-    }
-
-    /* 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.handle_route = avsys_audio->user_route_policy;
-
-    return TRUE;
-}
-
-static gboolean
-gst_avsysaudiosink_open (GstAudioSink * asink)
-{
-       return TRUE;
-}
-
-static gboolean
-gst_avsysaudiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
-{
-    GstAvsysAudioSink *avsys_audio = NULL;
-    guint      p_time = 0, b_time = 0;
-
-    avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
-
-    // set avsys audio param
-    if (!avsysaudiosink_parse_spec (avsys_audio, spec))
-        goto spec_parse;
-
-    if (gst_avsysaudiosink_avsys_open(avsys_audio) == FALSE)
-    {
-       GST_ERROR_OBJECT(avsys_audio, "gst_avsysaudiosink_avsys_open() failed");
-        return FALSE;
-    }
-
-
-    /* Ring buffer size */
-    if (AVSYS_STATE_SUCCESS ==
-       avsys_audio_get_period_buffer_time(avsys_audio->audio_handle, &p_time, &b_time))
-    {
-       if(p_time == 0 || b_time == 0)
-               return FALSE;
-
-       spec->latency_time = (guint64)p_time;
-       spec->buffer_time = (guint64)b_time;
-    }
-    else
-    {
-       return FALSE;
-    }
-    spec->segsize = avsys_audio->avsys_size; /* '/16' see avsys_audio_open */
-    spec->segtotal = (b_time / p_time) + (((b_time % p_time)/p_time > 0.5) ? 1: 0);
-       //spec->segtotal+2;
-
-       GST_WARNING_OBJECT (avsys_audio, "latency time %u, buffer time %u, seg total %u\n",
-                       (unsigned int)(spec->latency_time/1000), (unsigned int)(spec->buffer_time/1000), spec->segtotal);
-    return TRUE;
-
-spec_parse:
-       {
-               GST_ELEMENT_ERROR (avsys_audio, RESOURCE, SETTINGS, (NULL),
-                                                  ("Setting of swparams failed: " ));
-               return FALSE;
-       }
-}
-
-static gboolean
-gst_avsysaudiosink_unprepare (GstAudioSink * asink)
-{
-    GstAvsysAudioSink  *avsys_audio = NULL;
-    gboolean                   result = TRUE;
-    avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
-
-    if(!gst_avsysaudiosink_avsys_close(avsys_audio))
-    {
-       GST_ERROR_OBJECT(avsys_audio, "gst_avsysaudiosink_avsys_close() failed");
-       result = FALSE;
-    }
-
-    return result;
-}
-
-static gboolean
-gst_avsysaudiosink_close (GstAudioSink * asink)
-{
-    GstAvsysAudioSink *avsys_audio = NULL;
-
-    avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
-    gst_caps_replace (&avsys_audio->cached_caps, NULL);
-
-    return TRUE;
-}
-
-
-/*
- *   Underrun and suspend recovery
- */
-
-static guint
-gst_avsysaudiosink_write (GstAudioSink * asink, gpointer data, guint length)
-{
-    GstAvsysAudioSink *avsys_audio = NULL;
-    gint       write_len = 0;
-
-    avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
-    GST_AVSYS_AUDIO_SINK_LOCK (asink);
-
-    if(avsys_audio->audio_stream_cb == NULL)
-    {
-       write_len = avsys_audio_write(avsys_audio->audio_handle, data, length);
-    
-#if defined (LPCM_DUMP_SUPPORT)
-               fwrite(data, 1, write_len, avsys_audio->dumpFp); //This is for original data (no volume convert)
-#endif
-        if(write_len != length)
-        {
-            goto write_error;
-        }
-    
-        GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
-    
-        return write_len;
-write_error:
-        {
-            GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
-
-            if(AVSYS_FAIL(write_len))
-               {
-                       GST_ERROR_OBJECT(avsys_audio, "avsys_audio_write() failed with %d\n", write_len);
-               }
-            return length;              /* skip one period */
-
-        }
-    }
-    else
-    {
-       gboolean result;
-       result = avsys_audio->audio_stream_cb(data, length, avsys_audio->cbHandle);
-       if(!result)
-       {
-               GST_ERROR_OBJECT(avsys_audio,"auido stream callback failed\n");
-       }
-        GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
-        return length;
-    }
-}
-
-static guint
-gst_avsysaudiosink_delay (GstAudioSink * asink)
-{
-       GstAvsysAudioSink       *avsys_audio = NULL;
-       int                                     delay = 0;
-       guint                           retValue = 0;
-
-       avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
-       GST_AVSYS_AUDIO_SINK_RESET_LOCK (asink);
-       if((int)avsys_audio->audio_handle != -1) {
-               if(AVSYS_STATE_SUCCESS == avsys_audio_delay(avsys_audio->audio_handle, &delay)) {
-                       retValue = delay;
-               }
-       }
-       GST_AVSYS_AUDIO_SINK_RESET_UNLOCK (asink);
-       return retValue;
-}
-
-static void
-gst_avsysaudiosink_reset (GstAudioSink * asink)
-{
-    GstAvsysAudioSink *avsys_audio = NULL;
-    int avsys_result = AVSYS_STATE_SUCCESS;
-
-    GST_AVSYS_AUDIO_SINK_LOCK (asink);
-    avsys_audio = GST_AVSYS_AUDIO_SINK (asink);
-
-#if defined(__REPLACE_RESET_WITH_CLOSE_AND_REOPEN__)
-    GST_AVSYS_AUDIO_SINK_RESET_LOCK (asink);
-       avsys_result = avsys_audio_close (avsys_audio->audio_handle);
-       if(AVSYS_FAIL(avsys_result))
-       {
-               GST_ERROR_OBJECT (avsys_audio, "avsys_audio_close: internal error: ");
-       }
-       else
-       {
-               avsys_audio->audio_handle =(avsys_handle_t) -1;
-       }
-       GST_AVSYS_AUDIO_SINK_RESET_UNLOCK (asink);
-#else
-    if(AVSYS_STATE_SUCCESS != avsys_audio_reset(avsys_audio->audio_handle))
-    {
-       GST_ERROR_OBJECT (avsys_audio, "avsys-reset: internal error: ");
-    }
-#endif
-
-    GST_AVSYS_AUDIO_SINK_UNLOCK (asink);
-
-    return;
-}
-
-
-static gboolean
-gst_avsysaudiosink_avsys_open(GstAvsysAudioSink *avsys_audio)
-{
-    int avsys_result;
-
-       GST_AVSYS_AUDIO_SINK_LOCK(avsys_audio);
-    if(avsys_audio->audio_handle == (avsys_handle_t)-1) {
-
-               GST_LOG_OBJECT (avsys_audio, "avsys_audio_open() with user policy [%d] ",  avsys_audio->user_route_policy);
-
-               avsys_result = avsys_audio_open(&avsys_audio->audio_param, &avsys_audio->audio_handle, &avsys_audio->avsys_size);
-        if(avsys_result != AVSYS_STATE_SUCCESS)
-        {
-               GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
-               avsysaudiosink_post_message(avsys_audio, avsys_result);
-            return FALSE;
-        }
-
-        GST_LOG_OBJECT (avsys_audio, "Opened av system ");
-
-        GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
-
-    }
-    else {
-       GST_WARNING_OBJECT(avsys_audio, "audio handle has already opened");
-        GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
-        return FALSE;
-    }
-#if defined (LPCM_DUMP_SUPPORT)
-    if(avsys_audio->dumpFp == NULL)
-    {
-       avsys_audio->dumpFp = fopen("/root/dump.lpcm","w");
-    }
-#endif
-    return TRUE;
-}
-
-static gboolean
-gst_avsysaudiosink_avsys_close(GstAvsysAudioSink *avsys_audio)
-{
-    int avsys_result = AVSYS_STATE_SUCCESS;
-
-    GST_AVSYS_AUDIO_SINK_LOCK (avsys_audio);
-
-    if(avsys_audio->audio_handle !=  (avsys_handle_t)-1 )
-    {
-       avsys_result = avsys_audio_close(avsys_audio->audio_handle);
-
-       if (AVSYS_FAIL(avsys_result))
-               {
-                       GST_ERROR_OBJECT(avsys_audio,
-                                       "avsys_audio_close() failed with 0x%x", avsys_result);
-                       GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
-                       return FALSE;
-               }
-               else
-               {
-                       avsys_audio->audio_handle = (avsys_handle_t) -1;
-                       GST_INFO_OBJECT(avsys_audio, "avsys_audio_close() success");
-               }
-
-        GST_LOG_OBJECT (avsys_audio, "Closed av system ");
-    }
-    else
-    {
-       GST_WARNING_OBJECT(avsys_audio, "audio handle has already closed");
-    }
-
-       GST_AVSYS_AUDIO_SINK_UNLOCK (avsys_audio);
-#if defined (LPCM_DUMP_SUPPORT)
-       if(avsys_audio->dumpFp != NULL)
-       {
-               fclose(avsys_audio->dumpFp);
-               avsys_audio->dumpFp = NULL;
-       }
-#endif
-       return TRUE;
-}
-
-static GstStateChangeReturn
-gst_avsyssudiosink_change_state (GstElement *element, GstStateChange transition)
-{
-    GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-    GstAvsysAudioSink *avsys_audio = GST_AVSYS_AUDIO_SINK (element);
-
-    int avsys_result = AVSYS_STATE_SUCCESS;
-
-    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:
-#if defined(_ALSA_DAPM_)
-               switch(avsys_audio->audio_route_policy)
-               {
-               case AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING:
-                       GST_INFO_OBJECT(avsys_audio, "audio route uses external setting");
-                       break;
-               default:
-                       GST_ERROR_OBJECT(avsys_audio, "Unknown audio route option %d\n", avsys_audio->audio_route_policy);
-                       break;
-               }
-#endif
-#if defined(__REPLACE_RESET_WITH_CLOSE_AND_REOPEN__)
-               if(avsys_audio->audio_handle == (avsys_handle_t)-1)
-               {
-                       avsys_result = avsys_audio_open(&avsys_audio->audio_param, &avsys_audio->audio_handle, &avsys_audio->avsys_size);
-                       if(AVSYS_FAIL(avsys_result))
-                       {
-                               GST_ERROR_OBJECT (avsys_audio, "avsys_audio_open: internal error: ");
-                               return GST_STATE_CHANGE_FAILURE;
-                       }
-               }
-#endif
-
-                   if(avsys_audio->use_fadeup_volume) {
-                       GST_INFO_OBJECT(avsys_audio, "Set fadeup volume");
-                       avsys_audio_set_volume_fadeup(avsys_audio->audio_handle);
-                   }
-
-                   if(AVSYS_STATE_SUCCESS != avsys_audio_set_mute(avsys_audio->audio_handle, CONVERT_MUTE_VALUE(avsys_audio->mute)))
-                   {
-                       GST_ERROR_OBJECT(avsys_audio, "Set mute failed %d", CONVERT_MUTE_VALUE(avsys_audio->mute));
-                   }
-            break;
-        default:
-            break;
-    }
-    ret = GST_ELEMENT_CLASS(parent_class)->change_state (element, transition);
-    if (ret == GST_STATE_CHANGE_FAILURE)
-    {
-        return ret;
-    }
-    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 ret;
-}
-
-
-static gboolean
-avsysaudiosink_post_message(GstAvsysAudioSink* self,int errorcode)
-{
-               GST_DEBUG("avsysaudiosink_post_message\n");
-               gboolean ret = TRUE;
-               GstMessage *Msg = NULL;
-               GQuark domain;
-               gboolean status = FALSE;
-               GError *error = NULL;
-               gint error_code;
-               /*
-               if(errorcode>0)
-                               error_code = errorcode;
-               else
-                               error_code = GST_STREAM_ERROR_TYPE_NOT_FOUND; */
-               error_code = GST_RESOURCE_ERROR_FAILED;
-               domain = gst_resource_error_quark();
-               error = g_error_new (domain, error_code, "AVSYSAUDIOSINK_RESOURCE_ERROR");
-               Msg = gst_message_new_error(GST_ELEMENT(self), error, "AVSYSAUDIOSINK_ERROR");
-               status = gst_element_post_message (GST_ELEMENT(self), Msg);
-               if (status == FALSE)
-               {
-                               GST_ERROR("Error in posting message on the bus ...\n");
-                               ret = FALSE;
-               }
-
-               return ret;
-}
diff --git a/avsystem/src/gstavsysaudiosink.h b/avsystem/src/gstavsysaudiosink.h
deleted file mode 100644 (file)
index 04d5dce..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * avsystem
- *
- * 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_AVSYSAUDIOSINK_H__
-#define __GST_AVSYSAUDIOSINK_H__
-
-#include <gst/gst.h>
-#include <gst/audio/gstaudiosink.h>
-
-#include <avsys-audio.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_AVSYS_AUDIO_SINK             (gst_avsysaudiosink_get_type())
-#define GST_AVSYS_AUDIO_SINK(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVSYS_AUDIO_SINK,GstAvsysAudioSink))
-#define GST_AVSYS_AUDIO_SINK_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVSYS_AUDIO_SINK,GstAvsysAudioSinkClass))
-#define GST_IS_AVSYS_AUDIO_SINK(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVSYS_AUDIO_SINK))
-#define GST_IS_AVSYS_AUDIO_SINK_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVSYS_AUDIO_SINK))
-//#define GST_AVSYS_AUDIO_SINK_CAST(obj)        ((GstAvsysAudioSink *) (obj))
-
-typedef struct _GstAvsysAudioSink      GstAvsysAudioSink;
-typedef struct _GstAvsysAudioSinkClass GstAvsysAudioSinkClass;
-
-#define GST_AVSYS_AUDIO_SINK_GET_LOCK(obj) (GST_AVSYS_AUDIO_SINK (obj)->avsys_audio_lock)
-#define GST_AVSYS_AUDIO_SINK_LOCK(obj)     (g_mutex_lock (GST_AVSYS_AUDIO_SINK_GET_LOCK(obj)))
-#define GST_AVSYS_AUDIO_SINK_UNLOCK(obj)   (g_mutex_unlock (GST_AVSYS_AUDIO_SINK_GET_LOCK(obj)))
-
-#define GST_AVSYS_AUDIO_SINK_GET_RESET_LOCK(obj) (GST_AVSYS_AUDIO_SINK (obj)->avsys_audio_reset_lock)
-#define GST_AVSYS_AUDIO_SINK_RESET_LOCK(obj)     (g_mutex_lock (GST_AVSYS_AUDIO_SINK_GET_RESET_LOCK(obj)))
-#define GST_AVSYS_AUDIO_SINK_RESET_UNLOCK(obj)   (g_mutex_unlock (GST_AVSYS_AUDIO_SINK_GET_RESET_LOCK(obj)))
-
-
-typedef enum  {
-       AVSYSAUDIOSINK_AUDIO_UNMUTE = 0,
-       AVSYSAUDIOSINK_AUDIO_MUTE,
-       AVSYSAUDIOSINK_AUDIO_MUTE_WITH_FADEDOWN_EFFECT,
-}GstAvsysAudioSinkAudioMute;
-
-
-typedef enum  {
-       AVSYSAUDIOSINK_AUDIOROUTE_USE_EXTERNAL_SETTING = -1,
-       AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_NORMAL,
-       AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_ALERT,
-       AVSYSAUDIOSINK_AUDIOROUTE_PLAYBACK_HEADSET_ONLY
-}GstAvsysAudioSinkAudioRoutePolicy;
-
-
-typedef enum  {
-       AVSYSAUDIOSINK_USERROUTE_AUTO = 0,
-       AVSYSAUDIOSINK_USERROUTE_PHONE  
-}GstAvsysAudioSinkUserRoutePolicy;
-
-typedef enum {
-       AVSYSAUDIOSINK_LATENCY_LOW = 0,
-       AVSYSAUDIOSINK_LATENCY_MID,
-       AVSYSAUDIOSINK_LATENCY_HIGH,
-}GstAvsysAudioSinkLatency;
-
-#define GST_AVSYS_AUDIO_SINK_USER_ROUTE                (gst_avsysaudiosink_user_route_get_type ())
-#define GST_AVSYS_AUDIO_SINK_AUDIO_ROUTE       (gst_avsysaudiosink_audio_route_get_type ())
-#define GST_AVSYS_AUDIO_SINK_VOLUME_TABLE      (gst_avsysaudiosink_volume_table_get_type ())
-#define GST_AVSYS_AUDIO_SINK_VOLUME_TYPE               (gst_avsysaudiosink_volume_table_get_type ())
-#define GST_AVSYS_AUDIO_SINK_MUTE                      (gst_avsysaudiosink_audio_mute_get_type())
-#define GST_AVSYS_AUDIO_SINK_LATENCY_TYPE      (gst_avsysaudiosink_latency_get_type ())
-
-//this define if for debugging
-//#define LPCM_DUMP_SUPPORT
-struct _GstAvsysAudioSink {
-    GstAudioSink                               sink;
-
-       avsys_handle_t                          audio_handle;
-       avsys_audio_param_t             audio_param;
-       gint                            avsys_size;
-       gint                                            mute;
-       gint                                            use_fadeup_volume;
-       gint                                            audio_route_policy;
-       gint                                            user_route_policy;
-       gint                                            latency;
-
-       GstCaps                                         *cached_caps;
-
-       GMutex                                          *avsys_audio_lock;
-       GMutex                                          *avsys_audio_reset_lock;
-       gint                                            volume_type;
-       gint                                            sound_priority;
-       gint                                            bytes_per_sample;
-
-       gpointer                         cbHandle;
-       gboolean (*audio_stream_cb) (void *stream, int stream_size, void *user_param);
-};
-
-
-struct _GstAvsysAudioSinkClass {
-       GstAudioSinkClass    parent_class;
-};
-
-GType gst_avsysaudiosink_get_type (void);
-GType gst_avsysaudiosink_audio_route_get_type (void);
-GType gst_avsysaudiosink_volume_table_get_type (void);
-GType gst_avsysaudiosink_audio_mute_get_type(void);
-GType gst_avsysaudiosink_latency_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_AVSYSAUDIOSINK_H__ */
diff --git a/avsystem/src/gstavsysaudiosrc.c b/avsystem/src/gstavsysaudiosrc.c
deleted file mode 100644 (file)
index 3a4fdc0..0000000
+++ /dev/null
@@ -1,1005 +0,0 @@
-/*
- * avsystem
- *
- * 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
- *
- */
-
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <gst/gst.h>
-#include <gst/gstutils.h>
-//#include <mm_debug.h>
-
-#include <sys/time.h>  /*gettimeofday*/
-#include <unistd.h>
-
-#include "gstavsysaudiosrc.h"
-
-/**
- * Define for Release
- *
- * _ENABLE_FAKE_READ:          enable fake read instead of avsys_audio_read(). (default: 0)
- */
-#define        _ENABLE_FAKE_READ               0
-//#define      USE_GPT8
-
-
-#define _MIN_RATE              8000
-#define _MAX_RATE              48000
-#define _MIN_CHANNEL           1
-#define _MAX_CHANNEL           2
-
-
-#define DEFAULT_GPT8_FREQ 26
-
-#if _ENABLE_FAKE_READ
-static long g_delay_time;
-#endif
-
-#define DEFAULT_MEDIACALL_MODE AVSYS_AUDIO_ECHO_MODE_NONE
-#define DEFAULT_AUDIO_LATENCY  AVSYSAUDIOSRC_LATENCY_MID
-
-GST_DEBUG_CATEGORY_EXTERN (avsystem_src_debug);
-#define GST_CAT_DEFAULT avsystem_src_debug
-
-/* elementfactory information */
-static const GstElementDetails gst_avsysaudiosrc_details =
-       GST_ELEMENT_DETAILS ("AV system source",
-                                                "Source/Audio",
-                                                "Read from a AV system audio in",
-                                                "Samsung Electronics co., ltd.");
-
-
-enum {
-       PROP_0,
-#if 0
-#if !defined(I386_SIMULATOR)
-    PROP_AUDIO_MEDIA_CALL,
-#endif
-#endif
-    PROP_AUDIO_LATENCY,
-};
-
-enum {
-       CAPTURE_UNCORK = 0,
-       CAPTURE_CORK,
-};
-
-GType
-gst_avsysaudiosrc_audio_latency_get_type (void)
-{
-  static GType capture_audio_latency_type = 0;
-  static const GEnumValue capture_audio_latency[] = {
-    {AVSYSAUDIOSRC_LATENCY_LOW, "Set capture latency as low", "low"},
-    {AVSYSAUDIOSRC_LATENCY_MID, "Set capture latency as mid", "mid"},
-    {AVSYSAUDIOSRC_LATENCY_HIGH, "Set capture latency as high", "high"},
-    {0, NULL, NULL},
-  };
-
-  if (!capture_audio_latency_type) {
-         capture_audio_latency_type =
-        g_enum_register_static ("GstAvsysAudioSrcAudioLatency", capture_audio_latency);
-  }
-  return capture_audio_latency_type;
-}
-
-
-GST_BOILERPLATE (GstAvsysAudioSrc, gst_avsysaudiosrc, GstAudioSrc, GST_TYPE_AUDIO_SRC);
-
-#if _ENABLE_FAKE_READ
-static unsigned long   fake_delay (unsigned long usec);
-#endif
-
-static guint gst_avsysaudiosrc_delay (GstAudioSrc *asrc);
-
-static void            gst_avsysaudiosrc_finalize              (GObject * object);
-static void            gst_avsysaudiosrc_set_property  (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
-static void            gst_avsysaudiosrc_get_property  (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
-
-static GstCaps*        gst_avsysaudiosrc_getcaps       (GstBaseSrc * bsrc);
-
-static gboolean        gst_avsysaudiosrc_open          (GstAudioSrc * asrc);
-static gboolean        gst_avsysaudiosrc_prepare       (GstAudioSrc * asrc, GstRingBufferSpec * spec);
-static gboolean        gst_avsysaudiosrc_unprepare     (GstAudioSrc * asrc);
-static gboolean        gst_avsysaudiosrc_close         (GstAudioSrc * asrc);
-static guint           gst_avsysaudiosrc_read          (GstAudioSrc * asrc, gpointer data, guint length);
-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);
-static GstCaps *gst_avsysaudiosrc_detect_formats (GstObject * obj,avsys_pcm_hw_params_t * hw_params,  GstCaps * in_caps);
-static GstCaps *gst_avsysaudiosrc_probe_supported_formats (GstObject * obj, avsys_handle_t handle, const GstCaps * template_caps);
-#endif
-static GstStateChangeReturn gst_avsys_src_change_state (GstElement * element, GstStateChange transition) ;
-
-
-
-/* AvsysAudioSrc signals and args */
-enum {
-       LAST_SIGNAL
-};
-
-# define AVSYS_AUDIO_SRC_FACTORY_ENDIANNESS   "LITTLE_ENDIAN"
-
-static GstStaticPadTemplate avsysaudiosrc_src_factory =
-       GST_STATIC_PAD_TEMPLATE ("src",
-                                                               GST_PAD_SRC,
-                                                               GST_PAD_ALWAYS,
-                                                               GST_STATIC_CAPS (
-                                                                       "audio/x-raw-int, "
-                                                                       "endianness = (int) { " AVSYS_AUDIO_SRC_FACTORY_ENDIANNESS " }, "
-                             "signed = (boolean) { TRUE }, "
-                                                                       "width = (int) 16, "
-                                                                       "depth = (int) 16, "
-                             "rate = (int) [ 8000, 48000 ], "
-                             "channels = (int) [ 1, 2 ]; "
-                                                                       "audio/x-raw-int, "
-                             "signed = (boolean) { FALSE }, "
-                                                                       "width = (int) 8, "
-                                                                       "depth = (int) 8, "
-                             "rate = (int) [ 8000, 48000 ], "
-                             "channels = (int) [ 1, 2 ]")
-                                                       );
-
-static inline guint _time_to_sample(GstAvsysAudioSrc *avsyssrc,  GstClockTime diff)
-{
-       guint result = 0;
-       // sample rate : asrc->audio_param.samplerate
-       result =(GST_TIME_AS_USECONDS(diff) * avsyssrc->audio_param.samplerate)/1000000;
-       return result;
-}
-
-
-static void
-gst_avsysaudiosrc_finalize (GObject * object)
-{
-    GstAvsysAudioSrc *src = NULL;
-
-
-    src = GST_AVSYS_AUDIO_SRC (object);
-       g_mutex_free (src->avsysaudio_lock);
-
-       G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_avsysaudiosrc_base_init (gpointer g_class)
-{
-       GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-       gst_element_class_set_details (element_class, &gst_avsysaudiosrc_details);
-
-       gst_element_class_add_pad_template (element_class,
-                                                                               gst_static_pad_template_get (&avsysaudiosrc_src_factory));
-}
-
-static void
-gst_avsysaudiosrc_class_init (GstAvsysAudioSrcClass * klass)
-{
-       GObjectClass *gobject_class;
-       GstElementClass *gstelement_class;
-       GstBaseSrcClass *gstbasesrc_class;
-       GstBaseAudioSrcClass *gstbaseaudiosrc_class;
-       GstAudioSrcClass *gstaudiosrc_class;
-
-       gobject_class = (GObjectClass *) klass;
-       gstelement_class = (GstElementClass *) klass;
-       gstbasesrc_class = (GstBaseSrcClass *) klass;
-       gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
-       gstaudiosrc_class = (GstAudioSrcClass *) klass;
-
-       gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_avsys_src_change_state);
-
-    parent_class = g_type_class_peek_parent (klass);
-
-       gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_avsysaudiosrc_finalize);
-       gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_avsysaudiosrc_get_property);
-       gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_avsysaudiosrc_set_property);
-#if defined(_USE_CAPS_)
-       gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_avsysaudiosrc_getcaps);
-#endif
-       gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_avsysaudiosrc_open);
-       gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_avsysaudiosrc_prepare);
-       gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_avsysaudiosrc_unprepare);
-       gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_avsysaudiosrc_close);
-       gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_avsysaudiosrc_read);
-       gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_avsysaudiosrc_delay);
-       gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_avsysaudiosrc_reset);
-
-       g_object_class_install_property (gobject_class ,PROP_AUDIO_LATENCY,
-                       g_param_spec_enum("latency", "Audio Latency",
-                                       "Audio latency",
-                                       GST_AVSYS_AUDIO_SRC_LATENCY, DEFAULT_AUDIO_LATENCY,
-                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
-}
-
-
-
-/**
- *@note useful range 0 - 1000000 microsecond
- */
-#if _ENABLE_FAKE_READ
-static unsigned long
-fake_delay (unsigned long usec)
-{
-       struct timeval s_time;
-       struct timeval c_time;
-       long s_sec  = 0L;
-       long s_usec = 0L;
-       long c_sec  = 0L;
-       long c_usec = 0L;
-       long t_sec  = 0L;
-       long t_usec = 0L;
-       unsigned long total_usec = 0UL;
-       unsigned long t = 0UL;
-
-       if (usec == 0UL) {
-               usleep (0);
-               return 0;
-       }
-
-       /*get start time*/
-       if (gettimeofday ((struct timeval *)&s_time, NULL) == 0) {
-               s_sec  = s_time.tv_sec;
-               s_usec = s_time.tv_usec;
-       } else {
-               return 0;
-       }
-
-       for (;;) {
-               /*get current time*/
-               if (gettimeofday ((struct timeval *)&c_time, NULL) == 0) {
-                       c_sec  = c_time.tv_sec;
-                       c_usec = c_time.tv_usec;
-               } else {
-                       return 0;
-               }
-
-               /*get elasped sec*/
-               t_sec = c_sec - s_sec;
-
-               /*get elapsed usec*/
-               if ((s_usec) > (c_usec)) {
-                       t_usec = 1000000L - (s_usec) + (c_usec);
-                       t_sec--;
-               } else {
-                       t_usec = (c_usec) - (s_usec);
-               }
-
-               /*get total elapsed time*/
-               total_usec = (t_sec * 1000000UL) + t_usec;
-
-               t = usec - total_usec;
-
-               if (total_usec >= usec) {
-                       break;
-               } else {
-                       if (t > 10000UL) {
-                               /*this function does not work in precision*/
-                               usleep (1);
-                       }
-               }
-       }
-
-       return total_usec;
-}
-#endif
-
-static guint
-gst_avsysaudiosrc_delay (GstAudioSrc *asrc)
-{
-       GstAvsysAudioSrc        *avsys_audio = NULL;
-       int                                     delay;
-       guint                           retValue = 0;
-
-       avsys_audio = GST_AVSYS_AUDIO_SRC (asrc);
-       if(AVSYS_STATE_SUCCESS == avsys_audio_delay(avsys_audio->audio_handle, &delay))
-               retValue = delay;
-
-       return retValue;
-}
-
-
-
-static void
-gst_avsysaudiosrc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
-{
-    GstAvsysAudioSrc *src = NULL;
-//    gint                     getvalue = 0;
-       src = GST_AVSYS_AUDIO_SRC (object);
-
-       if (src->cached_caps == NULL)
-       {
-               switch (prop_id)
-               {
-        case PROP_AUDIO_LATENCY:
-               src->latency = g_value_get_enum(value);
-                       break;
-        default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-               break;
-               }
-       }
-}
-
-static void
-gst_avsysaudiosrc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
-{
-       GstAvsysAudioSrc *src;
-
-       src = GST_AVSYS_AUDIO_SRC (object);
-
-    switch (prop_id)
-    {
-       case PROP_AUDIO_LATENCY:
-               g_value_set_enum(value, src->latency);
-               break;
-       default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-               break;
-       }
-}
-
-static void
-gst_avsysaudiosrc_init (GstAvsysAudioSrc * avsysaudiosrc, GstAvsysAudioSrcClass * g_class)
-{
-       GST_DEBUG_OBJECT (avsysaudiosrc, "initializing");
-
-       avsysaudiosrc->cached_caps = NULL;
-       avsysaudiosrc->audio_handle = (avsys_handle_t)-1;
-       avsysaudiosrc->buffer_size = 0;
-       avsysaudiosrc->avsysaudio_lock = g_mutex_new ();
-       avsysaudiosrc->latency = DEFAULT_AUDIO_LATENCY;
-}
-
-#if defined(_USE_CAPS_)
-static GstCaps *
-gst_avsysaudiosrc_getcaps (GstBaseSrc * bsrc)
-{
-    GstElementClass *element_class;
-    GstPadTemplate *pad_template;
-       GstAvsysAudioSrc *src;
-    GstCaps *caps = NULL;
-
-       src = GST_AVSYS_AUDIO_SRC (bsrc);
-
-    if(src->audio_handle==(avsys_handle_t)-1){
-       GST_DEBUG_OBJECT(src,"device not open, using template caps");
-       return NULL;
-    }
-
-    if (src->cached_caps)
-       {
-               GST_LOG_OBJECT (src, "Returning cached caps");
-            return gst_caps_ref(src->cached_caps);
-       }
-       element_class = GST_ELEMENT_GET_CLASS (src);
-       pad_template = gst_element_class_get_pad_template (element_class, "src");
-       g_return_val_if_fail (pad_template != NULL, NULL);
-
-       caps = gst_avsysaudiosrc_probe_supported_formats (GST_OBJECT (src), src->audio_handle,
-                                                                                                       gst_pad_template_get_caps (pad_template));
-
-       if (caps) {
-               src->cached_caps = gst_caps_ref (caps);
-       }
-
-       GST_INFO_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps);
-
-       return caps;
-}
-#endif
-static gboolean
-gst_avsysaudiosrc_open (GstAudioSrc * asrc)
-{
-       return TRUE;
-}
-
-static gboolean
-avsysaudiosrc_parse_spec (GstAvsysAudioSrc *avsys_audio, GstRingBufferSpec * spec)
-{
-    /* Check param */
-    if (spec->type != GST_BUFTYPE_LINEAR ||
-        spec->channels > 2 || spec->channels < 1 ||
-        !(spec->format == GST_S8 || spec->format == GST_S16_LE) )
-        return FALSE;
-
-    switch(spec->format)
-    {
-    case GST_S8:
-        avsys_audio->audio_param.format = AVSYS_AUDIO_FORMAT_8BIT;
-        avsys_audio->bytes_per_sample = 1;
-        break;
-    case GST_S16_LE:
-        avsys_audio->audio_param.format = AVSYS_AUDIO_FORMAT_16BIT;
-        avsys_audio->bytes_per_sample = 2;
-        break;
-    default:
-       GST_DEBUG_OBJECT(avsys_audio, "Only support S8, S16LE format");
-        return FALSE;
-    }
-
-    // set audio parameter for avsys audio open
-
-       switch(avsys_audio->latency)
-       {
-       case AVSYSAUDIOSRC_LATENCY_LOW:
-               avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_INPUT_LOW_LATENCY;
-               break;
-       case AVSYSAUDIOSRC_LATENCY_MID:
-               avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_INPUT;
-               break;
-       case AVSYSAUDIOSRC_LATENCY_HIGH:
-               avsys_audio->audio_param.mode = AVSYS_AUDIO_MODE_INPUT_HIGH_LATENCY;
-               break;
-       default:
-               break;
-       }
-
-    avsys_audio->audio_param.priority = 0;
-    avsys_audio->audio_param.samplerate = spec->rate;
-    avsys_audio->audio_param.channels = spec->channels;
-
-    if(spec->channels == 2)
-       avsys_audio->bytes_per_sample *= 2;
-    else if(spec->channels > 2)
-    {
-       GST_ERROR_OBJECT(avsys_audio,"Unsupported channel number %d", spec->channels);
-       return FALSE;
-    }
-
-    return TRUE;
-}
-
-static gboolean
-gst_avsysaudiosrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
-{
-    GstAvsysAudioSrc *avsysaudiosrc = NULL;
-       guint   p_time = 0, b_time = 0;
-
-       avsysaudiosrc = GST_AVSYS_AUDIO_SRC (asrc);
-
-    if (!avsysaudiosrc_parse_spec(avsysaudiosrc, spec))
-    {
-       GST_ERROR("avsysaudiosrc_parse_spec failed");
-        return FALSE;
-    }
-
-       /*open avsys audio*/
-    if (!gst_avsysaudiosrc_avsys_open (avsysaudiosrc))
-    {
-       GST_ERROR("gst_avsysaudiosrc_avsys_open failed");
-        return FALSE;
-    }
-
-    /* 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;
-
-       spec->latency_time = (guint64)p_time;
-       spec->buffer_time = (guint64)b_time;
-       }
-       else
-       {
-        return FALSE;
-       }
-       spec->segsize = avsysaudiosrc->buffer_size;
-       spec->segtotal = (b_time / p_time) + (((b_time % p_time)/p_time > 0.5) ? 1: 0);
-       spec->segtotal += 2;
-
-     GST_INFO_OBJECT(avsysaudiosrc, "audio buffer spec : latency_time(%llu), buffer_time(%llu), segtotal(%d), segsize(%d)\n",
-                                                       spec->latency_time, spec->buffer_time, spec->segtotal, spec->segsize);
-
-
-    return TRUE;
-}
-
-static gboolean
-gst_avsysaudiosrc_unprepare (GstAudioSrc * asrc)
-{
-    GstAvsysAudioSrc *avsysaudiosrc = NULL;
-    gboolean ret = TRUE;
-
-    avsysaudiosrc = GST_AVSYS_AUDIO_SRC (asrc);
-
-       /*close*/
-    GST_AVSYS_AUDIO_SRC_LOCK (avsysaudiosrc);
-
-    if(!gst_avsysaudiosrc_avsys_close(avsysaudiosrc))
-    {
-       GST_ERROR_OBJECT(avsysaudiosrc, "gst_avsysaudiosrc_avsys_close failed");
-       ret = FALSE;
-    }
-    GST_AVSYS_AUDIO_SRC_UNLOCK (asrc);
-
-
-
-       return ret;
-}
-
-static gboolean
-gst_avsysaudiosrc_close (GstAudioSrc * asrc)
-{
-    GstAvsysAudioSrc *avsysaudiosrc = NULL;
-
-    avsysaudiosrc = GST_AVSYS_AUDIO_SRC (asrc);
-       gst_caps_replace (&avsysaudiosrc->cached_caps, NULL);
-
-       return TRUE;
-}
-
-static void
-gst_avsysaudiosrc_reset (GstAudioSrc * asrc)
-{
-       GstAvsysAudioSrc *avsys_audio = NULL;
-
-    avsys_audio = GST_AVSYS_AUDIO_SRC (asrc);
-    GST_AVSYS_AUDIO_SRC_LOCK (asrc);
-
-    if(AVSYS_STATE_SUCCESS != avsys_audio_reset(avsys_audio->audio_handle))
-    {
-       GST_ERROR_OBJECT (avsys_audio, "avsys-reset: internal error: ");
-    }
-
-    GST_AVSYS_AUDIO_SRC_UNLOCK (asrc);
-
-    return;
-}
-
-
-static GstStateChangeReturn
-gst_avsys_src_change_state (GstElement * element, GstStateChange transition)
-{
-       GstAvsysAudioSrc *avsys = NULL;
-       GstStateChangeReturn ret ;
-
-       avsys = GST_AVSYS_AUDIO_SRC (element);
-       GST_DEBUG("gst_avsys_src_change_state");
-
-       switch (transition)
-       {
-               case GST_STATE_CHANGE_NULL_TO_READY:
-               {
-                       GST_DEBUG ("GST_STATE_CHANGE_NULL_TO_READY\n") ;
-                       break ;
-               }
-               case GST_STATE_CHANGE_READY_TO_PAUSED:
-               {
-                       GST_DEBUG ("GST_STATE_CHANGE_READY_TO_PAUSED\n") ;
-                       break ;
-               }
-               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:
-                       break ;
-       }
-
-       ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-       GST_DEBUG ("After parent_class->change_state...\n") ;
-       switch (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:
-               {
-                       GST_DEBUG ("GST_STATE_CHANGE_PAUSED_TO_READY\n") ;
-                       break ;
-               }
-               case GST_STATE_CHANGE_READY_TO_NULL:
-               {
-                       GST_DEBUG ("GST_STATE_CHANGE_READY_TO_NULL\n") ;
-                       break ;
-               }
-               default:
-                       break ;
-       }
-
-       return ret;
-}
-
-
-
-static guint
-gst_avsysaudiosrc_read (GstAudioSrc * asrc, gpointer data, guint length)
-{
-    GstAvsysAudioSrc   *avsysaudiosrc = NULL;
-       gint                            readed = 0;
-       gpointer                        ptr = NULL;
-       guint                           used_length = 0;
-
-       avsysaudiosrc = GST_AVSYS_AUDIO_SRC (asrc);
-
-       ptr = data;
-
-    GST_AVSYS_AUDIO_SRC_LOCK (avsysaudiosrc);
-#if _ENABLE_FAKE_READ
-       readed = avsysaudiosrc->buffer_size;
-       memset (ptr, 10, avsysaudiosrc->buffer_size);   /*maybe can't hear*/
-       fake_delay (1000000UL / g_delay_time);
-#else
-       ptr = data;
-       readed = avsys_audio_read (avsysaudiosrc->audio_handle, ptr, length);
-       if (readed < 0)
-               goto _READ_ERROR;
-#endif //_ENABLE_FAKE_READ
-       GST_AVSYS_AUDIO_SRC_UNLOCK (avsysaudiosrc);
-
-       return readed;
-
-_READ_ERROR:
-       {
-               GST_AVSYS_AUDIO_SRC_UNLOCK (asrc);
-               return length;  /* skip one period */
-       }
-}
-
-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;
-
-       GST_AVSYS_AUDIO_SRC_LOCK (avsysaudiosrc);
-
-       avsys_result = avsys_audio_open(&avsysaudiosrc->audio_param, &avsysaudiosrc->audio_handle, &avsysaudiosrc->buffer_size);
-
-       if (avsys_result != AVSYS_STATE_SUCCESS) {
-               GST_ERROR_OBJECT(avsysaudiosrc, "avsys_audio_open() error. [0x%x]\n", avsys_result);
-               GST_AVSYS_AUDIO_SRC_UNLOCK (avsysaudiosrc);
-               return FALSE;
-       }
-
-#if _ENABLE_FAKE_READ
-       g_delay_time = (unsigned long)((avsysaudiosrc->samplerate * (avsysaudiosrc->format / 8) * avsysaudiosrc->channels) / avsysaudiosrc->buffer_size);
-#endif
-
-       GST_AVSYS_AUDIO_SRC_UNLOCK (avsysaudiosrc);
-       return TRUE;
-}
-
-static gboolean
-gst_avsysaudiosrc_avsys_close(GstAvsysAudioSrc *src)
-{
-       int ret;
-
-    if (src->audio_handle != (avsys_handle_t)-1)
-    {
-               /*close avsys audio*/
-               ret = avsys_audio_close (src->audio_handle);
-        if (AVSYS_FAIL(ret))
-        {
-               GST_ERROR_OBJECT(src, "avsys_audio_close() error 0x%x", ret);
-                       return FALSE;
-               }
-        src->audio_handle = (avsys_handle_t)-1;
-        GST_DEBUG_OBJECT(src, "AVsys audio handle closed");
-       }
-    else
-    {
-       GST_WARNING_OBJECT(src,"avsys audio handle has already closed");
-    }
-
-       return TRUE;
-}
-#if defined(_USE_CAPS_)
-static GstCaps *
-gst_avsysaudiosrc_detect_rates(GstObject *obj,
-               avsys_pcm_hw_params_t *hw_params, GstCaps *in_caps)
-{
-       GstCaps *caps;
-       guint min, max;
-       gint err, dir, min_rate, max_rate, i;
-
-       GST_LOG_OBJECT(obj, "probing sample rates ...");
-
-       if ((err = avsys_pcm_hw_params_get_rate_min(hw_params, &min, &dir)) < 0)
-               goto min_rate_err;
-
-       if ((err = avsys_pcm_hw_params_get_rate_max(hw_params, &max, &dir)) < 0)
-               goto max_rate_err;
-
-       min_rate = min;
-       max_rate = max;
-
-       if (min_rate < _MIN_RATE)
-               min_rate = _MIN_RATE; /* random 'sensible minimum' */
-
-       if (max_rate <= 0)
-               max_rate = _MAX_RATE; /* or maybe just use 192400 or so? */
-       else if (max_rate > 0 && max_rate < _MIN_RATE)
-               max_rate = MAX (_MIN_RATE, min_rate);
-
-       GST_DEBUG_OBJECT(obj, "Min. rate = %u (%d)", min_rate, min);
-       GST_DEBUG_OBJECT(obj, "Max. rate = %u (%d)", max_rate, max);
-
-       caps = gst_caps_make_writable(in_caps);
-
-       for (i = 0; i < gst_caps_get_size(caps); ++i)
-       {
-               GstStructure *s;
-
-               s = gst_caps_get_structure(caps, i);
-               if (min_rate == max_rate)
-               {
-                       gst_structure_set(s, "rate", G_TYPE_INT, min_rate, NULL);
-               }
-               else
-               {
-                       gst_structure_set(s, "rate", GST_TYPE_INT_RANGE, min_rate,
-                                       max_rate, NULL);
-               }
-       }
-
-       return caps;
-       /* ERRORS */
-       min_rate_err:
-       {
-               GST_ERROR_OBJECT(obj, "failed to query minimum sample rate");
-               gst_caps_unref(in_caps);
-               return NULL;
-       }
-       max_rate_err:
-       {
-               GST_ERROR_OBJECT(obj, "failed to query maximum sample rate");
-               gst_caps_unref(in_caps);
-               return NULL;
-       }
-}
-
-
-static GstCaps *
-gst_avsysaudiosrc_detect_formats(GstObject * obj,
-               avsys_pcm_hw_params_t * hw_params, GstCaps * in_caps)
-{
-       avsys_pcm_format_mask_t *mask;
-       GstStructure *s;
-       GstCaps *caps;
-       gint i;
-
-       avsys_pcm_format_mask_malloc(&mask);
-       avsys_pcm_hw_params_get_format_mask(hw_params, mask);
-
-       caps = gst_caps_new_empty();
-
-       for (i = 0; i < gst_caps_get_size(in_caps); ++i)
-       {
-               GstStructure *scopy;
-               //gint w;
-               gint width = 0, depth = 0;
-               gint sndformat;
-
-               s = gst_caps_get_structure(in_caps, i);
-               if (!gst_structure_has_name(s, "audio/x-raw-int"))
-               {
-                       GST_WARNING_OBJECT(obj, "skipping non-int format");
-                       continue;
-               }
-               if (!gst_structure_get_int(s, "width", &width)
-                               || !gst_structure_get_int(s, "depth", &depth))
-                       continue;
-
-               GST_DEBUG_OBJECT(obj, "width = %d height = %d", width, depth);
-               if (width == 8)
-                       sndformat = 0;//SND_PCM_FORMAT_S8
-               else
-                       //width==16
-                       sndformat = 2; //SND_PCM_FORMAT_S16_LE
-               if (avsys_pcm_format_mask_test(mask, sndformat))
-               { //must be implemented
-                       /* template contains { true, false } or just one, leave it as it is */
-                       scopy = gst_structure_copy(s);
-
-               }
-               else
-               {
-                       scopy = NULL;
-               }
-               if (scopy)
-               {
-                       /* TODO: proper endianness detection, for now it's CPU endianness only */
-                       gst_structure_set(scopy, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
-                       gst_structure_set(scopy, "endianness", G_TYPE_INT, G_BYTE_ORDER,
-                                       NULL);
-                       gst_caps_append_structure(caps, scopy);
-               }
-
-       }
-
-       avsys_pcm_format_mask_free(mask);
-       gst_caps_unref(in_caps);
-       return caps;
-}
-
-
-static GstCaps *
-gst_avsysaudiosrc_detect_channels(GstObject * obj,
-               avsys_pcm_hw_params_t * hw_params, GstCaps * in_caps)
-{
-       GstCaps *caps;
-       guint min, max;
-       gint err, min_channel, max_channel, i;
-//     gint dir;
-
-       GST_LOG_OBJECT(obj, "probing sample rates ...");
-
-       if ((err = avsys_pcm_hw_params_get_channels_min(hw_params, &min)) < 0)
-               goto min_chan_err;
-
-       if ((err = avsys_pcm_hw_params_get_channels_max(hw_params, &max)) < 0)
-               goto max_chan_err;
-
-       min_channel = min;
-       max_channel = max;
-
-       if (min_channel < _MIN_CHANNEL)
-               min_channel = _MIN_CHANNEL; /* random 'sensible minimum' */
-
-       if (max_channel <= 0)
-               max_channel = _MAX_CHANNEL; /* or maybe just use 192400 or so? */
-       else if (max_channel > 0 && max_channel < _MIN_CHANNEL)
-               max_channel = MAX (_MAX_CHANNEL, min_channel);
-
-       GST_DEBUG_OBJECT(obj, "Min. channel = %u (%d)", min_channel, min);
-       GST_DEBUG_OBJECT(obj, "Max. channel = %u (%d)", max_channel, max);
-
-       caps = gst_caps_make_writable(in_caps);
-
-       for (i = 0; i < gst_caps_get_size(caps); ++i)
-       {
-               GstStructure *s;
-
-               s = gst_caps_get_structure(caps, i);
-               if (min_channel == max_channel)
-               {
-                       gst_structure_set(s, "channels", G_TYPE_INT, _MIN_CHANNEL, NULL);
-               }
-               else
-               {
-                       gst_structure_set(s, "channels", GST_TYPE_INT_RANGE, min_channel,
-                                       max_channel, NULL);
-               }
-       }
-
-       return caps;
-
-       /* ERRORS */
-       min_chan_err:
-       {
-               GST_ERROR_OBJECT(obj, "failed to query minimum sample rate");
-               gst_caps_unref(in_caps);
-               return NULL;
-       }
-       max_chan_err:
-       {
-               GST_ERROR_OBJECT(obj, "failed to query maximum sample rate:");
-               gst_caps_unref(in_caps);
-               return NULL;
-       }
-}
-
-/*
- * gst_avsys_probe_supported_formats:
- *
- * Takes the template caps and returns the subset which is actually
- * supported by this device.
- *
- */
-
-static GstCaps *
-gst_avsysaudiosrc_probe_supported_formats(GstObject * obj,
-               avsys_handle_t handle, const GstCaps * template_caps)
-{
-
-       avsys_pcm_hw_params_t *hw_params;
-       GstCaps *caps;
-       gint err;
-
-       avsys_pcm_hw_params_malloc(&hw_params);
-       if ((err = avsys_pcm_hw_params_any(handle, hw_params)) < 0)
-               goto error;
-
-       caps = gst_caps_copy(template_caps);
-
-       if (!(caps = gst_avsysaudiosrc_detect_formats(obj, hw_params, caps)))
-               goto subroutine_error;
-
-       if (!(caps = gst_avsysaudiosrc_detect_rates(obj, hw_params, caps)))
-               goto subroutine_error;
-
-       if (!(caps = gst_avsysaudiosrc_detect_channels(obj, hw_params, caps)))
-               goto subroutine_error;
-
-       avsys_pcm_hw_params_free(hw_params);
-       return caps;
-
-       /* ERRORS */
-       error:
-       {
-               GST_ERROR_OBJECT(obj, "failed to query formats");
-               return NULL;
-       }
-       subroutine_error:
-       {
-               GST_ERROR_OBJECT(obj, "failed to query formats");
-               return NULL;
-       }
-}
-#endif
diff --git a/avsystem/src/gstavsysaudiosrc.h b/avsystem/src/gstavsysaudiosrc.h
deleted file mode 100644 (file)
index 4031e04..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * avsystem
- *
- * 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_AVSYS_AUDIO_SRC_H__
-#define __GST_AVSYS_AUDIO_SRC_H__
-
-//#undef  _MMCAMCORDER_MERGE_TEMP 
-
-#include <gst/audio/gstaudiosrc.h>
-#include <glib.h>
-
-#include <avsys-audio.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_AVSYS_AUDIO_SRC            (gst_avsysaudiosrc_get_type())
-#define GST_AVSYS_AUDIO_SRC(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVSYS_AUDIO_SRC,GstAvsysAudioSrc))
-#define GST_AVSYS_AUDIO_SRC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVSYS_AUDIO_SRC,GstAvsysAudioSrcClass))
-#define GST_IS_AVSYS_AUDIO_SRC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVSYS_AUDIO_SRC))
-#define GST_IS_AVSYS_AUDIO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVSYS_AUDIO_SRC))
-#define GST_AVSYS_AUDIO_SRC_CAST(obj)       ((GstAvsysAudioSrc *)(obj))
-
-#define GST_AVSYS_AUDIO_SRC_GET_LOCK(obj)  (GST_AVSYS_AUDIO_SRC_CAST (obj)->avsysaudio_lock)
-#define GST_AVSYS_AUDIO_SRC_LOCK(obj)      (g_mutex_lock (GST_AVSYS_AUDIO_SRC_GET_LOCK (obj)))
-#define GST_AVSYS_AUDIO_SRC_UNLOCK(obj)    (g_mutex_unlock (GST_AVSYS_AUDIO_SRC_GET_LOCK (obj)))
-
-typedef struct _GstAvsysAudioSrc GstAvsysAudioSrc;
-typedef struct _GstAvsysAudioSrcClass GstAvsysAudioSrcClass;
-
-typedef enum {
-       AVSYSAUDIOSRC_LATENCY_LOW = 0,
-       AVSYSAUDIOSRC_LATENCY_MID,
-       AVSYSAUDIOSRC_LATENCY_HIGH,
-}GstAvsysAudioSrcAudioLatency;
-
-#define GST_AVSYS_AUDIO_SRC_LATENCY    (gst_avsysaudiosrc_audio_latency_get_type())
-
-
-
-/**
- * GstAvsysAudioSrc:
- *
- * Opaque data structure
- */
-struct _GstAvsysAudioSrc {
-       GstAudioSrc                                     src;
-
-       avsys_handle_t                          audio_handle;
-       avsys_audio_param_t             audio_param;
-
-       gint                                            buffer_size;
-       GstCaps                                         *cached_caps;
-       GMutex                                          *avsysaudio_lock;
-
-       gint                                            media_call;
-       gint                                            bytes_per_sample;
-       gint                                            latency;
-
-};
-
-struct _GstAvsysAudioSrcClass {
-       GstAudioSrcClass parent_class;
-};
-
-
-GType gst_avsysaudiosrc_get_type (void);
-GType gst_avsysaudiosrc_audio_latency_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_AVSYS_AUDIO_SRC_H__ */
diff --git a/avsystem/src/gstavsysmemsink.c b/avsystem/src/gstavsysmemsink.c
deleted file mode 100644 (file)
index 9d56985..0000000
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- * avsystem
- *
- * 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
- *
- */
-
-
-#if defined(_MM_PROJECT_FLOATER) || defined(_MM_PROJECT_PROTECTOR) || defined(_MM_PROJECT_VOLANS)
-#define VERSION "0.10.19" // sec
-#define PACKAGE "gstreamer"
-#elif defined(_MM_PROJECT_ADORA)
-#define VERSION "0.10.9" // mavell
-#define PACKAGE "gstreamer"
-#else
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "gstavsysmemsink.h"
-
-#define debug_enter g_print
-#define debug_leave g_print
-#define debug_fenter() g_print("enter: %s\n",__FUNCTION__)
-#define debug_fleave() g_print("leave: %s\n",__FUNCTION__)
-#define debug_msg g_print
-#define debug_verbose g_print
-#define debug_warning g_print
-#define debug_error g_print
-
-#define GST_CAT_DEFAULT avsysmemsink_debug
-
-#define DISABLE_YUV_FORMAT_ON_SINK_CAPS
-
-GST_DEBUG_CATEGORY_STATIC (avsysmemsink_debug);
-
-enum 
-{
-    SIGNAL_VIDEO_STREAM,
-    LAST_SIGNAL
-};
-
-enum 
-{
-       PROP_0,
-       PROP_WIDTH,
-       PROP_HEIGHT,
-       PROP_ROTATE,
-};
-
-static GstStaticPadTemplate sink_factory =
-       GST_STATIC_PAD_TEMPLATE ("sink",
-               GST_PAD_SINK, GST_PAD_ALWAYS,
-               GST_STATIC_CAPS (
-#ifndef DISABLE_YUV_FORMAT_ON_SINK_CAPS
-                       "video/x-raw-yuv, "
-                       "format = (fourcc){YV12}, "
-                       "framerate = (fraction) [ 0, MAX ], "
-                       "width = (int) [ 1, MAX ], "
-                       "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; "
-#else /* BGRA */
-                       "video/x-raw-rgb, "
-                       "bpp = (int)32, "
-                       "depth = (int)32, "
-                       "endianness = (int)4321, "
-                       "red_mask = (int)65280, "
-                       "green_mask = (int)16711680, "
-                       "blue_mask = (int)-16777216, "
-                       "alpha_mask = (int)255, "
-                       "width = (int) [ 1, MAX ], "
-                       "height = (int) [ 1, MAX ], "
-                       "framerate = (fraction) [ 0, MAX ]; "
-#endif
-               )
-       );
-
-static GstElementDetails AvsysMemSink_details = {
-            "AV-system Stream callback",
-            "Sink/Video", 
-            "Stream sink for AV-System GStreamer Plug-in", 
-            ""
-};
-
-static guint gst_avsysmemsink_signals[LAST_SIGNAL] = { 0 };
-
-
-#ifdef G_ENABLE_DEBUG
-#define g_marshal_value_peek_int(v)      g_value_get_int (v)
-#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
-#else /* !G_ENABLE_DEBUG */
-#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
-#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
-#endif /* !G_ENABLE_DEBUG */
-
-
-#define     GET_PIXEL(buf, x, y, stride)  (*((unsigned char*)(buf) + (x) + (y)*(stride)))
-
-#define     GET_RED(Y,U,V)     ((9535 * (Y - 16) + 13074 * (V - 128)) >> 13)
-#define     GET_GREEN(Y,U,V)  ((9535 * (Y - 16) - 6660 * (V - 128) - 3203 * (U - 128)) >> 13 )
-#define     GET_BLUE(Y,U,V)   ((9535 * (Y - 16) + 16531 * (U - 128)) >> 13 )
-
-#define     UCLIP(a) (((a)<0)?0:((a)>255)?255:(a))
-
-
-static void
-yuv420toargb(unsigned char *src, unsigned char *dst, int width, int height)
-{
-    int h,w;
-    int y=0,u=0,v=0;
-    int a=0,r=0,g=0,b=0;
-    
-    unsigned char* pixel;
-
-    int index=0;
-
-    unsigned char      *pY;
-    unsigned char      *pU;
-    unsigned char      *pV;
-
-    GST_DEBUG ("converting yuv420 to argb");
-
-    pY = src ;
-    pU = src + (width * height) ;
-    pV = src + (width * height) + (width * height /4) ;
-
-    a = 255;
-
-    for(h = 0 ; h < height; h++)
-    {
-        for(w = 0 ; w < width; w++)
-        {
-            y = GET_PIXEL(pY,w,h,width);
-            u = GET_PIXEL(pU,w/2,h/2,width/2);
-            v = GET_PIXEL(pV,w/2,h/2,width/2);
-
-            r = GET_RED(y,u,v);
-            g = GET_GREEN(y,u,v);
-            b = GET_BLUE(y,u,v);
-
-            r = UCLIP(r);
-            g = UCLIP(g);
-            b = UCLIP(b);
-
-            index = (w + (h* width)) * 4;
-            dst[index] = r;
-            dst[index+1] = g;
-            dst[index+2] = b;
-            dst[index+3] = a;
-        }
-    }
-}
-
-static void
-rotate_pure(unsigned char *src, unsigned char *dst, int width,int height,int angle,int bpp)
-{
-
-    int     size;
-    int     new_x,new_y;
-    int     org_x,org_y;
-    int     dst_width;
-    int     src_idx, dst_idx;
-    
-    size = width * height * bpp;
-    
-    if(angle == 0)
-    {
-        memcpy(dst,src,size);
-        return;
-    }
-
-    for(org_y =0; org_y < height; org_y++)
-    {
-        for(org_x = 0; org_x < width ; org_x++)
-        {
-            if(angle == 90)
-            {
-                new_x = height - org_y;
-                new_y = org_x;
-
-                dst_width = height;
-            }
-            else if(angle == 180)
-            {
-                new_x = width - org_x;
-                new_y = height - org_y;
-                dst_width = width;
-            }
-            else if(angle == 270)
-            {
-                new_x = org_y;
-                new_y = width - org_x;
-                dst_width = height;
-            }
-            else
-            {
-                g_print("Not support Rotate : %d\n",angle);
-                return;
-            }
-
-            src_idx = org_x + (org_y * width);
-            dst_idx = new_x + (new_y * dst_width);
-
-            memcpy(dst + (dst_idx*bpp), src+(src_idx *bpp),bpp);
-        }
-    }
-    
-}
-
-static void
-resize_pure(unsigned char *src, unsigned char *dst, int src_width, int src_height, int dst_width,int dst_height, int bpp)
-{
-    float      xFactor,yFactor;
-
-    float              org_fx,org_fy;
-    int                org_x,org_y;
-
-    int                x,y;
-
-    int                src_index,dst_index;
-
-    unsigned short *pshortSrc;
-    unsigned short *pshortDst;
-
-    if(bpp == 2)
-    {
-        pshortSrc = (unsigned short*)src;
-        pshortDst = (unsigned short*)dst;
-    }
-
-    xFactor = (float)((dst_width<<16) / src_width);
-    yFactor = (float)((dst_height<<16) / src_height);
-
-    for(y = 0; y < dst_height; y++)
-    {
-        for(x = 0; x < dst_width; x++)
-        {
-            org_fx = (float)((x<<16)/xFactor);
-            org_fy = (float)((y<<16)/yFactor);
-
-            org_x = (int)(org_fx);
-            org_y = (int)(org_fy);
-
-            src_index = org_x + (org_y * src_width);
-            dst_index = x + (y*dst_width);
-
-            memcpy(dst+(dst_index *bpp ),src+(src_index *bpp),bpp);
-        }
-    }
-}
-
-/* BOOLEAN:POINTER,INT,INT (avsysvideosink.c:1) */
-void
-gst_avsysmemsink_BOOLEAN__POINTER_INT_INT (GClosure         *closure,
-                                             GValue         *return_value G_GNUC_UNUSED,
-                                             guint          n_param_values,
-                                             const GValue   *param_values,
-                                             gpointer       invocation_hint G_GNUC_UNUSED,
-                                             gpointer       marshal_data)
-{
-    typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_INT_INT) (gpointer     data1,
-                                                                gpointer     arg_1,
-                                                                gint         arg_2,
-                                                                gint         arg_3,
-                                                                gpointer     data2);
-    register GMarshalFunc_BOOLEAN__POINTER_INT_INT callback;
-    register GCClosure *cc = (GCClosure*) closure;
-    register gpointer data1, data2;
-
-    gboolean v_return;
-
-    g_return_if_fail (return_value != NULL);
-    g_return_if_fail (n_param_values == 4);
-
-    if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-        data1 = closure->data;
-        data2 = g_value_peek_pointer (param_values + 0);
-    }
-    else
-    {
-        data1 = g_value_peek_pointer (param_values + 0);
-        data2 = closure->data;
-    }
-    callback = (GMarshalFunc_BOOLEAN__POINTER_INT_INT) (marshal_data ? marshal_data : cc->callback);
-
-    v_return = callback (data1,
-                        g_marshal_value_peek_pointer (param_values + 1),
-                        g_marshal_value_peek_int (param_values + 2),
-                        g_marshal_value_peek_int (param_values + 3),
-                        data2);
-
-    g_value_set_boolean (return_value, v_return);
-}
-
-static void gst_avsysmemsink_init_interfaces (GType type);
-
-
-GST_BOILERPLATE_FULL (GstAvsysMemSink, gst_avsysmemsink, GstVideoSink, GST_TYPE_VIDEO_SINK, gst_avsysmemsink_init_interfaces);
-
-
-static void 
-gst_avsysmemsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-       GstAvsysMemSink *AvsysMemSink = GST_AVSYS_MEM_SINK (object);
-       switch (prop_id) {
-               case PROP_0:
-                       break;
-               case PROP_WIDTH:
-               if(AvsysMemSink->dst_width != g_value_get_int (value))
-               {
-                               AvsysMemSink->dst_width = g_value_get_int (value);
-                    AvsysMemSink->dst_changed = 1;
-               }
-                       break;
-               case PROP_HEIGHT:
-                       if(AvsysMemSink->dst_height != g_value_get_int (value))
-                       {
-                               AvsysMemSink->dst_height = g_value_get_int (value);
-                    AvsysMemSink->dst_changed = 1;
-                       }
-                       break;
-          case PROP_ROTATE:
-               if(AvsysMemSink->rotate != g_value_get_int(value))
-               {
-                   AvsysMemSink->rotate = g_value_get_int(value);
-                   AvsysMemSink->dst_changed = 1;
-               }
-               break;
-               default:
-                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-                       g_print ("invalid property id\n");
-                       break;
-       };
-}
-
-static void 
-gst_avsysmemsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-       GstAvsysMemSink *AvsysMemSink = GST_AVSYS_MEM_SINK (object);
-
-       switch (prop_id) {
-               case PROP_0:
-                       break;
-               case PROP_WIDTH:
-                       g_value_set_int (value, AvsysMemSink->dst_width);
-                       break;
-               case PROP_HEIGHT:
-                       g_value_set_int (value, AvsysMemSink->dst_height);
-                       break;
-          case PROP_ROTATE:
-               g_value_set_int (value, AvsysMemSink->rotate);
-               break;
-               default:
-                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-                       debug_warning ("invalid property id\n");
-                       break;
-       }
-}
-
-static void
-free_buffer(GstAvsysMemSink *AvsysMemSink)
-{
-    if(AvsysMemSink->con_buf)
-        free(AvsysMemSink->con_buf);
-
-    if(AvsysMemSink->rot_buf)
-        free(AvsysMemSink->rot_buf);
-
-    if(AvsysMemSink->rsz_buf)
-        free(AvsysMemSink->rsz_buf);
-
-    AvsysMemSink->con_buf = NULL;
-    AvsysMemSink->rot_buf = NULL;
-    AvsysMemSink->rsz_buf = NULL;
-
-}
-static GstStateChangeReturn 
-gst_avsysmemsink_change_state (GstElement *element, GstStateChange transition)
-{
-       GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-       GstAvsysMemSink *AvsysMemSink = GST_AVSYS_MEM_SINK (element);
-       switch (transition) {
-               case GST_STATE_CHANGE_NULL_TO_READY:
-                       debug_msg ("GST AVSYS DISPLAY SINK: NULL -> READY\n");
-                       break;
-               case GST_STATE_CHANGE_READY_TO_PAUSED:
-                       debug_msg ("GST AVSYS DISPLAY SINK: READY -> PAUSED\n");
-                       break;
-               case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-                       debug_msg ("GST AVSYS DISPLAY SINK: PAUSED -> PLAYING\n");
-                       break;
-               default:
-                       break;
-       }
-
-       ret = GST_ELEMENT_CLASS(parent_class)->change_state (element, transition);
-       if (ret == GST_STATE_CHANGE_FAILURE) {
-               return ret;
-       }
-
-       switch (transition) {
-               case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-                       debug_msg ("GST AVSYS MEM SINK: PLAYING -> PAUSED\n");
-                       break;
-               case GST_STATE_CHANGE_PAUSED_TO_READY:
-                       debug_msg ("GST AVSYS MEM SINK: PAUSED -> READY\n");
-               free_buffer(AvsysMemSink);        
-                       break;
-               case GST_STATE_CHANGE_READY_TO_NULL:
-                       debug_msg ("GST AVSYS MEM SINK: READY -> NULL\n");
-                       break;
-               default:
-                       break;
-       }
-
-       return ret;
-
-
-}
-
-
-static gboolean
-gst_avsysmemsink_set_caps (GstBaseSink * bs, GstCaps * caps)
-{
-    GstAvsysMemSink *s = GST_AVSYS_MEM_SINK (bs);
-    GstStructure *structure;
-    gint width = 0;
-    gint height = 0;
-
-    if (caps != NULL)
-    {
-        guint32 fourcc;
-        char *name = NULL;
-        int bpp = 0, depth = 0;
-
-        structure = gst_caps_get_structure (caps, 0);
-
-        /**/
-        name = (char *) gst_structure_get_name (structure);
-        GST_DEBUG_OBJECT (s, "CAPS NAME: %s", name);
-
-               if (gst_structure_has_name (structure, "video/x-raw-rgb"))
-               {
-                       s->is_rgb = TRUE;
-               }
-               else if (gst_structure_has_name (structure, "video/x-raw-yuv")) 
-               {
-                       s->is_rgb = FALSE;
-               }
-
-        /* get source size */
-        gst_structure_get_int (structure, "height", &height);
-        gst_structure_get_int (structure, "width", &width);
-
-        if (gst_structure_get_fourcc (structure, "format", &fourcc)) 
-        {
-            switch (fourcc) 
-            {
-                case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
-                    debug_warning("set format AVSYS_VIDEO_FORMAT_UYVY\n");
-                    break;
-                case GST_MAKE_FOURCC ('Y', 'V', '1', '6'):
-                case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
-                    debug_warning("set format AVSYS_VIDEO_FORMAT_YUV422\n");
-                    break;
-                case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
-                    debug_warning("set format AVSYS_VIDEO_FORMAT_YUV420\n");
-                    break;
-                case GST_MAKE_FOURCC ('R', 'G', 'B', ' '):
-                    debug_warning("set format AVSYS_VIDEO_FORMAT_RGB565\n");
-                    break;
-                default:
-                    debug_warning("set default format AVSYS_VIDEO_FORMAT_RGB565\n");
-                    break;
-            }
-        }
-
-        if( s->src_width != width || 
-            s->src_height != height) 
-        {
-            debug_warning ("DISPLAY: Video Source Changed! [%d x %d] -> [%d x %d]\n",
-                                    s->src_width, s->src_height, width, height);
-            s->src_changed = TRUE;
-        }
-
-        s->src_width = width;
-        s->src_height = height;
-
-        if(s->dst_width ==0)
-        {
-            s->dst_width = width;
-            s->dst_changed = 1;
-        }
-
-        if(s->dst_height == 0)
-        {
-            s->dst_height = height;
-            s->dst_changed = 1;            
-        }
-        debug_msg ("SRC CAPS: width:%d, height:%d \n", width, height);
-    } 
-    else 
-    {
-        debug_warning ("caps is NULL.\n");
-    }
-
-    debug_fleave ();
-
-    return TRUE;
-}
-
-static GstFlowReturn
-gst_avsysmemsink_preroll (GstBaseSink * bsink, GstBuffer * buf)
-{
-       GstAvsysMemSink *AvsysMemSink = GST_AVSYS_MEM_SINK (bsink);
-
-       AvsysMemSink->src_length = GST_BUFFER_SIZE (buf);
-       debug_msg ("SRC LENGTH: %d\n", AvsysMemSink->src_length);
-
-       return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_avsysmemsink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
-{
-       GstAvsysMemSink *s = GST_AVSYS_MEM_SINK (bsink);
-       gboolean res = FALSE;
-       int f_size;
-       f_size = GST_BUFFER_SIZE (buf);
-       unsigned char       *dst_buf;
-
-       if ( ! s->is_rgb )
-       {
-           GST_DEBUG_OBJECT (s, "src format is not rgb");
-           if (s->dst_changed == TRUE)
-           {
-               if(s->con_buf)
-               {
-                   free(s->con_buf);
-                   s->con_buf = NULL;
-               }
-
-               if(s->rot_buf)
-               {
-                   free(s->rot_buf);
-                   s->rot_buf = NULL;
-               }
-
-               if(s->rsz_buf)
-               {
-                   free(s->rsz_buf);
-                   s->rsz_buf = NULL;
-               }
-
-               s->con_buf = malloc(s->src_width * s->src_height * 4);
-               if(s->rotate != 0)
-               {
-                   s->rot_buf = malloc(s->src_width * s->src_height * 4);
-               }
-
-               s->rsz_buf = malloc(s->dst_width * s->dst_height *4);
-               
-               s->dst_changed = FALSE;
-           } 
-
-           yuv420toargb(GST_BUFFER_DATA (buf),s->con_buf,s->src_width, s->src_height);
-           if(s->rotate != 0)
-           {
-               rotate_pure(s->con_buf,s->rot_buf,s->src_width, s->src_height,s->rotate,4);
-               if(s->rotate == 90 || s->rotate == 270)
-               {
-                   resize_pure(s->rot_buf,s->rsz_buf,s->src_height,s->src_width,
-                               s->dst_width, s->dst_height,4);
-               }
-               else
-               {
-                   resize_pure(s->rot_buf,s->rsz_buf,s->src_width,s->src_height,
-                               s->dst_width, s->dst_height,4);
-               }
-           }
-           else
-           {
-               resize_pure(s->con_buf,s->rsz_buf,s->src_width,s->src_height,
-                               s->dst_width, s->dst_height,4);
-           }
-
-           /* emit signal for video-stream */
-           g_signal_emit (s,gst_avsysmemsink_signals[SIGNAL_VIDEO_STREAM],
-                           0,s->rsz_buf,
-                           s->dst_width,s->dst_height,
-                           &res);
-       }
-       else
-       {
-               GST_DEBUG_OBJECT (s, "src format is rgb");
-
-               /* NOTE : video can be resized by convert plugin's set caps on running time. 
-                * So, it should notice it to application through callback func.
-                */
-                g_signal_emit (s, gst_avsysmemsink_signals[SIGNAL_VIDEO_STREAM],
-                                   0, GST_BUFFER_DATA (buf),
-                                   s->src_width, s->src_height,
-                                   &res);
-        }
-        GST_DEBUG_OBJECT (s, "g_signal_emit : src_width=%d, src_height=%d, GST_BUFFER_SIZE=%d", s->src_width,s->src_height,GST_BUFFER_SIZE(buf));
-
-    /*check video stream callback result.*/
-    if (res) 
-    {
-        //debug_verbose("Video stream is called.\n");
-        return GST_FLOW_OK;
-    }
-
-    return GST_FLOW_OK;
-}
-
-static void
-gst_avsysmemsink_init_interfaces (GType type)
-{
-       /*void*/
-}
-
-
-static void 
-gst_avsysmemsink_base_init (gpointer klass)
-{
-       GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
-       gst_element_class_add_pad_template (element_class, 
-                                gst_static_pad_template_get (&sink_factory));
-       gst_element_class_set_details (element_class, &AvsysMemSink_details);
-}
-
-static void 
-gst_avsysmemsink_class_init (GstAvsysMemSinkClass *klass)
-{
-       GObjectClass *gobject_class  = (GObjectClass*) klass;
-       GstElementClass *gstelement_class = (GstElementClass*) klass;
-       GstBaseSinkClass *gstbasesink_class = (GstBaseSinkClass *) klass;
-
-    
-       parent_class = g_type_class_peek_parent (klass);
-
-       gobject_class->set_property = gst_avsysmemsink_set_property;
-       gobject_class->get_property = gst_avsysmemsink_get_property;
-
-
-       g_object_class_install_property (gobject_class, PROP_WIDTH,
-                                                                               g_param_spec_int ("width",
-                                                                                                       "Width",
-                                                                                                       "Width of display",
-                                                                                                       0, G_MAXINT, 176,
-                                                                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-
-       g_object_class_install_property (gobject_class, PROP_HEIGHT,
-                                                                               g_param_spec_int ("height",
-                                                                                                       "Height",
-                                                                                                       "Height of display",
-                                                                                                       0, G_MAXINT, 144,
-                                                                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-       g_object_class_install_property (gobject_class, PROP_ROTATE,
-                                                                               g_param_spec_int ("rotate",
-                                                                                                       "Rotate",
-                                                                                                       "Rotate of display",
-                                                                                                       0, G_MAXINT, 0,
-                                                                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-
-       /**
-       * GstAvsysVideoSink::video-stream:
-       */
-       gst_avsysmemsink_signals[SIGNAL_VIDEO_STREAM] = g_signal_new (
-                                                       "video-stream",
-                                                       G_TYPE_FROM_CLASS (klass),
-                                                       G_SIGNAL_RUN_LAST,
-                                                       0,
-                                                       NULL,
-                                                       NULL,
-                                                       gst_avsysmemsink_BOOLEAN__POINTER_INT_INT,
-                                                       G_TYPE_BOOLEAN,
-                                                       3,
-                                                       G_TYPE_POINTER, G_TYPE_INT, G_TYPE_INT);
-
-    gstelement_class->change_state = gst_avsysmemsink_change_state;
-
-    gstbasesink_class->set_caps = gst_avsysmemsink_set_caps;
-    gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_avsysmemsink_preroll);
-    gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_avsysmemsink_show_frame);
-
-    
-    GST_DEBUG_CATEGORY_INIT (avsysmemsink_debug, 
-                            "avsysmemsink",
-                            0,
-                            "AV system based GStreamer Plug-in");
-}
-
-
-static void 
-gst_avsysmemsink_init (GstAvsysMemSink *AvsysMemSink, GstAvsysMemSinkClass *klass)
-{
-    /*private*/
-    AvsysMemSink->src_width = 0;
-    AvsysMemSink->src_height = 0;
-
-    AvsysMemSink->src_changed = 0;
-
-    /*property*/
-    AvsysMemSink->dst_width = 0;
-    AvsysMemSink->dst_height = 0;
-
-    AvsysMemSink->dst_changed = 0;
-
-    AvsysMemSink->rotate = 0;
-
-    AvsysMemSink->con_buf = NULL;
-    AvsysMemSink->rot_buf = NULL;
-    AvsysMemSink->rsz_buf = NULL;
-
-       AvsysMemSink->is_rgb = FALSE;
-}
-
-
-/* EOF */
diff --git a/avsystem/src/gstavsysmemsink.h b/avsystem/src/gstavsysmemsink.h
deleted file mode 100644 (file)
index bc28029..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * avsystem
- *
- * 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_AVSYSMEMSINK_H__
-#define __GST_AVSYSMEMSINK_H__
-
-#include <gst/gst.h>
-#include <gst/video/gstvideosink.h>
-#include <gst/interfaces/xoverlay.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_AVSYS_MEM_SINK             (gst_avsysmemsink_get_type())
-#define GST_AVSYS_MEM_SINK(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVSYS_MEM_SINK, GstAvsysMemSink))
-#define GST_AVSYS_MEM_SINK_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVSYS_MEM_SINK, GstAvsysMemSinkClass))
-#define GST_IS_AVSYS_MEM_SINK(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVSYS_MEM_SINK))
-#define GST_IS_AVSYS_MEM_SINK_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVSYS_MEM_SINK))
-
-
-typedef struct _GstAvsysMemSink      GstAvsysMemSink;
-typedef struct _GstAvsysMemSinkClass GstAvsysMemSinkClass;
-
-struct _GstAvsysMemSink
-{
-    GstVideoSink        videosink;
-
-    int                 src_width;
-    int                 src_height;
-
-    int                 src_changed;
-    int                 src_length;
-
-
-    int                 dst_width;
-    int                 dst_height;
-
-    int                 dst_length;
-    int                 dst_changed;
-
-    unsigned char       *con_buf;
-    unsigned char       *rot_buf;
-    unsigned char       *rsz_buf;
-
-       int                 rotate;
-
-       int                             is_rgb;
-};
-
-struct _GstAvsysMemSinkClass
-{
-       GstVideoSinkClass parent_class;
-};
-
-GType gst_avsysmemsink_get_type (void);
-
-G_END_DECLS
-
-
-#endif /* __GST_AVSYSMEMSINK_H__ */
-
-/* EOF */
diff --git a/avsystem/src/gstavsyssink.c b/avsystem/src/gstavsyssink.c
deleted file mode 100644 (file)
index a1ab29e..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * avsystem
- *
- * 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 <gst/gst.h>
-#include "gstavsysaudiosink.h"
-#include "gstavsysmemsink.h"
-
-GST_DEBUG_CATEGORY (avsystem_sink_debug);
-
-static gboolean
-plugin_init (GstPlugin *plugin)
-{
-       gboolean error;
-       /*register the exact name you can find in the framework*/
-       error = gst_element_register (plugin, "avsysaudiosink",
-                                                                 GST_RANK_PRIMARY + 100,
-                                                                 GST_TYPE_AVSYS_AUDIO_SINK);
-
-       error = gst_element_register (plugin, "avsysmemsink",
-                                                                 GST_RANK_NONE,
-                                                                 GST_TYPE_AVSYS_MEM_SINK);
-
-       if (!error)
-               goto failed;
-
-       GST_DEBUG_CATEGORY_INIT (avsystem_sink_debug, "avsystemsink", 0, "avsystem sink plugins");
-       return TRUE;
-
-failed:
-
-       return FALSE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-               GST_VERSION_MINOR,
-               "avsyssink",
-               "AV system video/audio sink plug-in",
-               plugin_init,
-               PACKAGE_VERSION,
-               "LGPL",
-               "AV System Sink",
-               "http://www.samsung.com")
diff --git a/avsystem/src/gstavsyssrc.c b/avsystem/src/gstavsyssrc.c
deleted file mode 100644 (file)
index adde8df..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * avsystem
- *
- * 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 <gst/gst.h>
-
-#include "gstavsysaudiosrc.h"
-
-GST_DEBUG_CATEGORY (avsystem_src_debug);
-
-static gboolean
-plugin_init (GstPlugin *plugin)
-{
-       gboolean error;
-       /*register the exact name you can find in the framework*/
-       error = gst_element_register (plugin, "avsysaudiosrc",
-                                                                 GST_RANK_NONE,
-                                                                 GST_TYPE_AVSYS_AUDIO_SRC);
-       if (!error)
-               goto failed;
-
-       GST_DEBUG_CATEGORY_INIT (avsystem_src_debug, "avsystemsrc", 0, "avsystem src plugins");
-       return TRUE;
-
-failed:
-
-       return FALSE;
-}
-
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-               GST_VERSION_MINOR,
-               "avsysaudiosrc",
-               "AV system audio source plug-in",
-               plugin_init,
-               PACKAGE_VERSION,
-               "LGPL",
-               "AV System Source",
-               "http://www.samsung.com")
-
diff --git a/common/m4/gst-x11.m4 b/common/m4/gst-x11.m4
new file mode 100644 (file)
index 0000000..d3baf2d
--- /dev/null
@@ -0,0 +1,70 @@
+dnl macros for X-related detections
+dnl AC_SUBST's HAVE_X, X_CFLAGS, X_LIBS
+AC_DEFUN([AG_GST_CHECK_X],
+[
+  AC_PATH_XTRA
+  ac_cflags_save="$CFLAGS"
+  ac_cppflags_save="$CPPFLAGS"
+  CFLAGS="$CFLAGS $X_CFLAGS"
+  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+
+  dnl now try to find the HEADER
+  AC_CHECK_HEADER(X11/Xlib.h, HAVE_X="yes", HAVE_X="no")
+
+  if test "x$HAVE_X" = "xno"
+  then
+    AC_MSG_NOTICE([cannot find X11 development files])
+  else
+    dnl this is much more than we want
+    X_LIBS="$X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS"
+    dnl AC_PATH_XTRA only defines the path needed to find the X libs,
+    dnl it does not add the libs; therefore we add them here
+    X_LIBS="$X_LIBS -lX11"
+    AC_SUBST(X_CFLAGS)
+    AC_SUBST(X_LIBS)
+  fi
+  AC_SUBST(HAVE_X)
+
+  CFLAGS="$ac_cflags_save"
+  CPPFLAGS="$ac_cppflags_save"
+])
+
+dnl *** XVideo ***
+dnl Look for the PIC library first, Debian requires it.
+dnl Check debian-devel archives for gory details.
+dnl 20020110:
+dnl At the moment XFree86 doesn't distribute shared libXv due
+dnl to unstable API.  On many platforms you CAN NOT link a shared
+dnl lib to a static non-PIC lib.  This is what the xvideo GStreamer
+dnl plug-in wants to do.  So Debian distributes a PIC compiled
+dnl version of the static lib for plug-ins to link to when it is
+dnl inappropriate to link the main application to libXv directly.
+dnl FIXME: add check if this platform can support linking to a
+dnl        non-PIC libXv, if not then don not use Xv.
+dnl FIXME: perhaps warn user if they have a shared libXv since
+dnl        this is an error until XFree86 starts shipping one
+AC_DEFUN([AG_GST_CHECK_XV],
+[
+  if test x$HAVE_X = xyes; then
+    AC_CHECK_LIB(Xv_pic, XvQueryExtension,
+                 HAVE_XVIDEO="yes", HAVE_XVIDEO="no",
+                 $X_LIBS -lXext)
+
+    if test x$HAVE_XVIDEO = xyes; then
+      XVIDEO_LIBS="-lXv_pic -lXext"
+      AC_SUBST(XVIDEO_LIBS)
+    else
+      dnl try again using something else if we didn't find it first
+      if test x$HAVE_XVIDEO = xno; then
+        AC_CHECK_LIB(Xv, XvQueryExtension,
+                   HAVE_XVIDEO="yes", HAVE_XVIDEO="no",
+                   $X_LIBS -lXext)
+
+        if test x$HAVE_XVIDEO = xyes; then
+          XVIDEO_LIBS="-lXv -lXext"
+          AC_SUBST(XVIDEO_LIBS)
+        fi
+      fi
+    fi
+  fi
+])
diff --git a/compile b/compile
new file mode 100755 (executable)
index 0000000..1b1d232
--- /dev/null
+++ b/compile
@@ -0,0 +1,142 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand `-c -o'.
+
+scriptversion=2005-05-14.22
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand `-c -o'.
+Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file `INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit $?
+    ;;
+esac
+
+ofile=
+cfile=
+eat=
+
+for arg
+do
+  if test -n "$eat"; then
+    eat=
+  else
+    case $1 in
+      -o)
+       # configure might choose to run compile as `compile cc -o foo foo.c'.
+       # So we strip `-o arg' only if arg is an object.
+       eat=1
+       case $2 in
+         *.o | *.obj)
+           ofile=$2
+           ;;
+         *)
+           set x "$@" -o "$2"
+           shift
+           ;;
+       esac
+       ;;
+      *.c)
+       cfile=$1
+       set x "$@" "$1"
+       shift
+       ;;
+      *)
+       set x "$@" "$1"
+       shift
+       ;;
+    esac
+  fi
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no `-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # `.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use `[/.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
+while true; do
+  if mkdir "$lockdir" >/dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+  mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+  mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/config.guess b/config.guess
new file mode 100755 (executable)
index 0000000..40eaed4
--- /dev/null
@@ -0,0 +1,1517 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+#   2011 Free Software Foundation, Inc.
+
+timestamp='2011-05-11'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner.  Please send patches (context
+# diff format) to <config-patches@gnu.org> and include a ChangeLog
+# entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
+Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           armeb) machine=armeb-unknown ;;
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           sh5el) machine=sh5le-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep -q __ELF__
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       # Debian GNU/NetBSD machines have a different userland, and
+       # thus, need a distinct triplet. However, they do not need
+       # kernel version information, so it can be replaced with a
+       # suitable tag, in the style of linux-gnu.
+       case "${UNAME_VERSION}" in
+           Debian*)
+               release='-gnu'
+               ;;
+           *)
+               release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+               ;;
+       esac
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit ;;
+    *:OpenBSD:*:*)
+       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+       exit ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit ;;
+    *:SolidBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+       exit ;;
+    macppc:MirBSD:*:*)
+       echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    alpha:OSF1:*:*)
+       case $UNAME_RELEASE in
+       *4.0)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+               ;;
+       *5.*)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+               ;;
+       esac
+       # According to Compaq, /usr/sbin/psrinfo has been available on
+       # OSF/1 and Tru64 systems produced since 1995.  I hope that
+       # covers most systems running today.  This code pipes the CPU
+       # types through head -n 1, so we only detect the type of CPU 0.
+       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+       case "$ALPHA_CPU_TYPE" in
+           "EV4 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "EV4.5 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "LCA4 (21066/21068)")
+               UNAME_MACHINE="alpha" ;;
+           "EV5 (21164)")
+               UNAME_MACHINE="alphaev5" ;;
+           "EV5.6 (21164A)")
+               UNAME_MACHINE="alphaev56" ;;
+           "EV5.6 (21164PC)")
+               UNAME_MACHINE="alphapca56" ;;
+           "EV5.7 (21164PC)")
+               UNAME_MACHINE="alphapca57" ;;
+           "EV6 (21264)")
+               UNAME_MACHINE="alphaev6" ;;
+           "EV6.7 (21264A)")
+               UNAME_MACHINE="alphaev67" ;;
+           "EV6.8CB (21264C)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8AL (21264B)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8CX (21264D)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.9A (21264/EV69A)")
+               UNAME_MACHINE="alphaev69" ;;
+           "EV7 (21364)")
+               UNAME_MACHINE="alphaev7" ;;
+           "EV7.9 (21364A)")
+               UNAME_MACHINE="alphaev79" ;;
+       esac
+       # A Pn.n version is a patched version.
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+       exitcode=$?
+       trap '' 0
+       exit $exitcode ;;
+    Alpha\ *:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit ;;
+    *:z/VM:*:*)
+       echo s390-ibm-zvmoe
+       exit ;;
+    *:OS400:*:*)
+       echo powerpc-ibm-os400
+       exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+       echo arm-unknown-riscos
+       exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+       case `/usr/bin/uname -p` in
+           sparc) echo sparc-icl-nx7; exit ;;
+       esac ;;
+    s390x:SunOS:*:*)
+       echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+       echo i386-pc-auroraux${UNAME_RELEASE}
+       exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+       eval $set_cc_for_build
+       SUN_ARCH="i386"
+       # If there is a compiler, see if it is configured for 64-bit objects.
+       # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+       # This test works for both compilers.
+       if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+           if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+               (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+               grep IS_64BIT_ARCH >/dev/null
+           then
+               SUN_ARCH="x86_64"
+           fi
+       fi
+       echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit ;;
+    sun*:*:4.2BSD:*)
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       case "`/bin/arch`" in
+           sun3)
+               echo m68k-sun-sunos${UNAME_RELEASE}
+               ;;
+           sun4)
+               echo sparc-sun-sunos${UNAME_RELEASE}
+               ;;
+       esac
+       exit ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+       echo m68k-milan-mint${UNAME_RELEASE}
+       exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+       echo m68k-hades-mint${UNAME_RELEASE}
+       exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+       echo m68k-unknown-mint${UNAME_RELEASE}
+       exit ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c &&
+         dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+         SYSTEM_NAME=`$dummy $dummyarg` &&
+           { echo "$SYSTEM_NAME"; exit; }
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit ;;
+    Motorola:*:4.3:PL8-*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit ;;
+    AViiON:dgux:*:*)
+       # DG/UX returns AViiON for all architectures
+       UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+           else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+           fi
+       else
+           echo i586-dg-dgux${UNAME_RELEASE}
+       fi
+       exit ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+       exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+               then
+                       echo "$SYSTEM_NAME"
+               else
+                       echo rs6000-ibm-aix3.2.5
+               fi
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit ;;
+    *:AIX:*:[4567])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                   sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                   case "${sc_cpu_version}" in
+                     523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                     528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                     532)                      # CPU_PA_RISC2_0
+                       case "${sc_kernel_bits}" in
+                         32) HP_ARCH="hppa2.0n" ;;
+                         64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                       esac ;;
+                   esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^            //' << EOF >$dummy.c
+
+               #define _HPUX_SOURCE
+               #include <stdlib.h>
+               #include <unistd.h>
+
+               int main ()
+               {
+               #if defined(_SC_KERNEL_BITS)
+                   long bits = sysconf(_SC_KERNEL_BITS);
+               #endif
+                   long cpu  = sysconf (_SC_CPU_VERSION);
+
+                   switch (cpu)
+                       {
+                       case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+                       case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+                       case CPU_PA_RISC2_0:
+               #if defined(_SC_KERNEL_BITS)
+                           switch (bits)
+                               {
+                               case 64: puts ("hppa2.0w"); break;
+                               case 32: puts ("hppa2.0n"); break;
+                               default: puts ("hppa2.0"); break;
+                               } break;
+               #else  /* !defined(_SC_KERNEL_BITS) */
+                           puts ("hppa2.0"); break;
+               #endif
+                       default: puts ("hppa1.0"); break;
+                       }
+                   exit (0);
+               }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   test -z "$HP_ARCH" && HP_ARCH=hppa
+               fi ;;
+       esac
+       if [ ${HP_ARCH} = "hppa2.0w" ]
+       then
+           eval $set_cc_for_build
+
+           # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+           # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+           # generating 64-bit code.  GNU and HP use different nomenclature:
+           #
+           # $ CC_FOR_BUILD=cc ./config.guess
+           # => hppa2.0w-hp-hpux11.23
+           # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+           # => hppa64-hp-hpux11.23
+
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+               grep -q __LP64__
+           then
+               HP_ARCH="hppa2.0w"
+           else
+               HP_ARCH="hppa64"
+           fi
+       fi
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+               { echo "$SYSTEM_NAME"; exit; }
+       echo unknown-hitachi-hiuxwe2
+       exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+       exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+       exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+       exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+       exit ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    *:UNICOS/mp:*:*)
+       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+       FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+       echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit ;;
+    5000:UNIX_System_V:4.*:*)
+       FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+       FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+       echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:FreeBSD:*:*)
+       case ${UNAME_MACHINE} in
+           pc98)
+               echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           amd64)
+               echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           *)
+               echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+       esac
+       exit ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit ;;
+    *:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit ;;
+    i*:windows32*:*)
+       # uname -m includes "-pc" on this system.
+       echo ${UNAME_MACHINE}-mingw32
+       exit ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit ;;
+    *:Interix*:*)
+       case ${UNAME_MACHINE} in
+           x86)
+               echo i586-pc-interix${UNAME_RELEASE}
+               exit ;;
+           authenticamd | genuineintel | EM64T)
+               echo x86_64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+           IA64)
+               echo ia64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+       esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+       echo i${UNAME_MACHINE}-pc-mks
+       exit ;;
+    8664:Windows_NT:*)
+       echo x86_64-pc-mks
+       exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i586-pc-interix
+       exit ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+       echo x86_64-unknown-cygwin
+       exit ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    *:GNU:*:*)
+       # the GNU system
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit ;;
+    *:GNU/*:*:*)
+       # other systems with GNU libc and userland
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+       exit ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit ;;
+    alpha:Linux:*:*)
+       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+         EV5)   UNAME_MACHINE=alphaev5 ;;
+         EV56)  UNAME_MACHINE=alphaev56 ;;
+         PCA56) UNAME_MACHINE=alphapca56 ;;
+         PCA57) UNAME_MACHINE=alphapca56 ;;
+         EV6)   UNAME_MACHINE=alphaev6 ;;
+         EV67)  UNAME_MACHINE=alphaev67 ;;
+         EV68*) UNAME_MACHINE=alphaev68 ;;
+       esac
+       objdump --private-headers /bin/sh | grep -q ld.so.1
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit ;;
+    arm*:Linux:*:*)
+       eval $set_cc_for_build
+       if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+           | grep -q __ARM_EABI__
+       then
+           echo ${UNAME_MACHINE}-unknown-linux-gnu
+       else
+           if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+               | grep -q __ARM_PCS_VFP
+           then
+               echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+           else
+               echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+           fi
+       fi
+       exit ;;
+    avr32*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    cris:Linux:*:*)
+       echo cris-axis-linux-gnu
+       exit ;;
+    crisv32:Linux:*:*)
+       echo crisv32-axis-linux-gnu
+       exit ;;
+    frv:Linux:*:*)
+       echo frv-unknown-linux-gnu
+       exit ;;
+    i*86:Linux:*:*)
+       LIBC=gnu
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #ifdef __dietlibc__
+       LIBC=dietlibc
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+       echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+       exit ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m32r*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef ${UNAME_MACHINE}
+       #undef ${UNAME_MACHINE}el
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=${UNAME_MACHINE}el
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=${UNAME_MACHINE}
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       ;;
+    or32:Linux:*:*)
+       echo or32-unknown-linux-gnu
+       exit ;;
+    padre:Linux:*:*)
+       echo sparc-unknown-linux-gnu
+       exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    tile*:Linux:*:*)
+       echo ${UNAME_MACHINE}-tilera-linux-gnu
+       exit ;;
+    vax:Linux:*:*)
+       echo ${UNAME_MACHINE}-dec-linux-gnu
+       exit ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit ;;
+    xtensa*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    i*86:DYNIX/ptx:4*:*)
+       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+       # earlier versions are messed up and put the nodename in both
+       # sysname and nodename.
+       echo i386-sequent-sysv4
+       exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+       # Unixware is an offshoot of SVR4, but it has its own version
+       # number series starting with 2...
+       # I am not positive that other SVR4 systems won't match this,
+       # I just have to hope.  -- rms.
+       # Use sysv4.2uw... so that sysv4* matches it.
+       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       exit ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit ;;
+    i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+       fi
+       exit ;;
+    i*86:*:5:[678]*)
+       # UnixWare 7.x, OpenUNIX and OpenServer 6.
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit ;;
+    pc:*:*:*)
+       # Left here for compatibility:
+       # uname -m prints for DJGPP always 'pc', but it prints nothing about
+       # the processor, so we play safe by assuming i586.
+       # Note: whatever this is, it MUST be the same as what config.sub
+       # prints for the "djgpp" host, or else GDB configury will decide that
+       # this is a cross-build.
+       echo i586-pc-msdosdjgpp
+       exit ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+       echo m68k-convergent-sysv
+       exit ;;
+    M680?0:D-NIX:5.3:*)
+       echo m68k-diab-dnix
+       exit ;;
+    M68*:*:R3V[5678]*:*)
+       test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+       OS_REL='.3'
+       test -r /etc/.relid \
+           && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+           && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit ;;
+    PENTIUM:*:4.0*:*)  # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                       # says <Richard.M.Bartel@ccMail.Census.GOV>
+       echo i586-unisys-sysv4
+       exit ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit ;;
+    i*86:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo ${UNAME_MACHINE}-stratus-vos
+       exit ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+       exit ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit ;;
+    BePC:Haiku:*:*)    # Haiku running on Intel PC compatible.
+       echo i586-pc-haiku
+       exit ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-6:SUPER-UX:*:*)
+       echo sx6-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-7:SUPER-UX:*:*)
+       echo sx7-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8:SUPER-UX:*:*)
+       echo sx8-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8R:SUPER-UX:*:*)
+       echo sx8r-nec-superux${UNAME_RELEASE}
+       exit ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Darwin:*:*)
+       UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+       case $UNAME_PROCESSOR in
+           i386)
+               eval $set_cc_for_build
+               if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+                 if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+                     (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+                     grep IS_64BIT_ARCH >/dev/null
+                 then
+                     UNAME_PROCESSOR="x86_64"
+                 fi
+               fi ;;
+           unknown) UNAME_PROCESSOR=powerpc ;;
+       esac
+       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+       exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit ;;
+    NEO-?:NONSTOP_KERNEL:*:*)
+       echo neo-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+       echo nse-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit ;;
+    SEI:*:*:SEIUX)
+       echo mips-sei-seiux${UNAME_RELEASE}
+       exit ;;
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit ;;
+    *:*VMS:*:*)
+       UNAME_MACHINE=`(uname -p) 2>/dev/null`
+       case "${UNAME_MACHINE}" in
+           A*) echo alpha-dec-vms ; exit ;;
+           I*) echo ia64-dec-vms ; exit ;;
+           V*) echo vax-dec-vms ; exit ;;
+       esac ;;
+    *:XENIX:*:SysV)
+       echo i386-pc-xenix
+       exit ;;
+    i*86:skyos:*:*)
+       echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+       exit ;;
+    i*86:rdos:*:*)
+       echo ${UNAME_MACHINE}-pc-rdos
+       exit ;;
+    i*86:AROS:*:*)
+       echo ${UNAME_MACHINE}-pc-aros
+       exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+       "4"
+#else
+       ""
+#endif
+       ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+       { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit ;;
+    c34*)
+       echo c34-convex-bsd
+       exit ;;
+    c38*)
+       echo c38-convex-bsd
+       exit ;;
+    c4*)
+       echo c4-convex-bsd
+       exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644 (file)
index 0000000..be0c437
--- /dev/null
@@ -0,0 +1,68 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define the version */
+#undef GST_PLUGIN_VERSION
+
+/* Define the release version */
+#undef GST_PLUGIN_VERSION_RELEASE
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
index 316d441..ee6ab18 100755 (executable)
@@ -1,6 +1,6 @@
 
 AC_INIT(extension, 1.0)
+
 dnl versions of gstreamer and plugins-base
 GST_MAJORMINOR=0.10
 GST_REQUIRED=0.10.0
@@ -39,10 +39,10 @@ AC_PROG_LIBTOOL
 
 dnl decide on error flags
 AS_COMPILER_FLAG(-Wall, GST_WALL="yes", GST_WALL="no")
-                                                                                
+
 if test "x$GST_WALL" = "xyes"; then
    GST_ERROR="$GST_ERROR -Wall"
-                                                                                
+
 #   if test "x$GST_PLUGIN_CVS" = "xyes"; then
 #     AS_COMPILER_FLAG(-Werror,GST_ERROR="$GST_ERROR -Werror",GST_ERROR="$GST_ERROR")
 #   fi
@@ -160,12 +160,47 @@ PKG_CHECK_MODULES(GST_INTERFACES, gstreamer-interfaces-$GST_MAJORMINOR >= $GST_R
 AC_SUBST(GST_INTERFACES_CFLAGS)
 AC_SUBST(GST_INTERFACES_LIBS)
 
+dnl xvimagesrc _CFLAGS and _LIB available
+
+PKG_CHECK_MODULES(DRI2, libdri2)
+AC_SUBST(DRI2_CFLAGS)
+AC_SUBST(DRI2_LIBS)
+
+PKG_CHECK_MODULES(X11, x11)
+AC_SUBST(X11_CFLAGS)
+AC_SUBST(X11_LIBS)
+
+PKG_CHECK_MODULES(XEXT, xext)
+AC_SUBST(XEXT_CFLAGS)
+AC_SUBST(XEXT_LIBS)
+
+PKG_CHECK_MODULES(XV, xv)
+AC_SUBST(XV_CFLAGS)
+AC_SUBST(XV_LIBS)
+
+PKG_CHECK_MODULES(XDAMAGE, xdamage)
+AC_SUBST(XDAMAGE_CFLAGS)
+AC_SUBST(XDAMAGE_LIBS)
+
+PKG_CHECK_MODULES(DRM, libdrm)
+AC_SUBST(DRM_CFLAGS)
+AC_SUBST(DRM_LIBS)
+
+PKG_CHECK_MODULES(DRM, libdrm-devel)
+AC_SUBST(DRM_DEVEL_CFLAGS)
+AC_SUBST(DRM_DEVEL_LIBS)
+
+PKG_CHECK_MODULES(TBM, libtbm)
+AC_SUBST(TBM_CFLAGS)
+AC_SUBST(TBM_LIBS)
+
 dnl use time analysis module
-PKG_CHECK_MODULES(MMTA, mm-ta)
-AC_SUBST(MMTA_CFLAGS)
-AC_SUBST(MMTA_LIBS)
 
-dnl required package for evasimagesink
+PKG_CHECK_MODULES(XML2, libxml-2.0)
+AC_SUBST(XML2_CFLAGS)
+AC_SUBST(XML2_LIBS)
+
+dnl required package for evasimagesink/evaspixmapsink
 PKG_CHECK_MODULES(EFL, [
   evas >= $EFL_REQUIRED
   ecore >= $EFL_REQUIRED
@@ -182,6 +217,88 @@ PKG_CHECK_MODULES(EFL, [
   ])
 ])
 
+dnl *** belows are related to evaspixmapsink plug-ins ***
+AG_GST_ARG_WITH_PACKAGE_NAME
+AG_GST_ARG_WITH_PACKAGE_ORIGIN
+
+dnl set license and copyright notice
+GST_LICENSE="LGPL"
+AC_DEFINE_UNQUOTED(GST_LICENSE, "$GST_LICENSE", [GStreamer license])
+AC_SUBST(GST_LICENSE)
+
+echo
+AC_MSG_NOTICE([Checking libraries for evaspixmapsink plugin])
+echo
+dnl *** X11 ***
+translit(dnm, m, l) AM_CONDITIONAL(USE_X, true)
+AG_GST_CHECK_FEATURE(X, [X libraries and plugins],
+                  [evaspixmapsink], [
+  AC_PATH_XTRA
+  ac_cflags_save="$CFLAGS"
+  ac_cppflags_save="$CPPFLAGS"
+  CFLAGS="$CFLAGS $X_CFLAGS"
+  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+
+  dnl now try to find the HEADER
+  AC_CHECK_HEADER(X11/Xlib.h, HAVE_X="yes", HAVE_X="no")
+
+  if test "x$HAVE_X" = "xno"
+  then
+    AC_MSG_NOTICE([cannot find X11 development files])
+  else
+    dnl this is much more than we want
+    X_LIBS="$X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS"
+    dnl AC_PATH_XTRA only defines the path needed to find the X libs,
+    dnl it does not add the libs; therefore we add them here
+    X_LIBS="$X_LIBS -lX11"
+    AC_SUBST(X_CFLAGS)
+    AC_SUBST(X_LIBS)
+  fi
+  AC_SUBST(HAVE_X)
+  CFLAGS="$ac_cflags_save"
+  CPPFLAGS="$ac_cppflags_save"
+])
+
+dnl Check for Xv extension
+translit(dnm, m, l) AM_CONDITIONAL(USE_XVIDEO, true)
+AG_GST_CHECK_FEATURE(XVIDEO, [X11 XVideo extensions],
+                  [evaspixmapsink], [
+AG_GST_CHECK_XV
+])
+
+dnl check for X Shm
+translit(dnm, m, l) AM_CONDITIONAL(USE_XSHM, true)
+AG_GST_CHECK_FEATURE(XSHM, [X Shared Memory extension], , [
+  if test x$HAVE_X = xyes; then
+    AC_CHECK_LIB(Xext, XShmAttach,
+                HAVE_XSHM="yes", HAVE_XSHM="no",
+                $X_LIBS)
+    if test "x$HAVE_XSHM" = "xyes"; then
+      XSHM_LIBS="-lXext"
+    else
+      dnl On AIX, it is in XextSam instead, but we still need -lXext
+      AC_CHECK_LIB(XextSam, XShmAttach,
+                  HAVE_XSHM="yes", HAVE_XSHM="no",
+                  $X_LIBS)
+      if test "x$HAVE_XSHM" = "xyes"; then
+       XSHM_LIBS="-lXext -lXextSam"
+      fi
+    fi
+  fi
+], , [
+  AC_SUBST(HAVE_XSHM)
+  AC_SUBST(XSHM_LIBS)
+])
+
+dnl use tbm
+PKG_CHECK_MODULES(TBM, libtbm)
+AC_SUBST(TBM_CFLAGS)
+AC_SUBST(TBM_LIBS)
+
+PKG_CHECK_MODULES(VCONF, vconf)
+AC_SUBST(VCONF_CFLAGS)
+AC_SUBST(VCONF_LIBS)
+
 dnl PKG_CHECK_MODULES(UDEVMGR, unified-dev-mgr)
 dnl AC_SUBST(UDEVMGR_CFLAGS)
 dnl AC_SUBST(UDEVMGR_LIBS)
@@ -198,18 +315,6 @@ AC_ARG_ENABLE(ext-encodebin, AC_HELP_STRING([--enable-ext-encodebin], [using enc
   [GST_EXT_USE_EXT_ENCODEBIN=yes])
 AM_CONDITIONAL(GST_EXT_USE_EXT_ENCODEBIN, test "x$GST_EXT_USE_EXT_ENCODEBIN" = "xyes")
 
-dnl use ext-avsystem --------------------------------------------------------------------------
-AC_ARG_ENABLE(ext-avsystem, AC_HELP_STRING([--enable-ext-avsystem], [using avsystem]),
-  [
-    case "${enableval}" in
-      yes) GST_EXT_USE_EXT_AVSYSTEM=yes ;;
-      no)  GST_EXT_USE_EXT_AVSYSTEM=no ;;
-      *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ext-avsystem) ;;
-    esac
-  ],
-  [GST_EXT_USE_EXT_AVSYSTEM=yes])
-AM_CONDITIONAL(GST_EXT_USE_EXT_AVSYSTEM, test "x$GST_EXT_USE_EXT_AVSYSTEM" = "xyes")
-
 dnl use ext-evasimagesink --------------------------------------------------------------------------
 AC_ARG_ENABLE(ext-evasimagesink, AC_HELP_STRING([--enable-ext-evasimagesink], [using evasimagesink]),
   [
@@ -222,30 +327,40 @@ AC_ARG_ENABLE(ext-evasimagesink, AC_HELP_STRING([--enable-ext-evasimagesink], [u
   [GST_EXT_USE_EXT_EVASIMAGESINK=yes])
 AM_CONDITIONAL(GST_EXT_USE_EXT_EVASIMAGESINK, test "x$GST_EXT_USE_EXT_EVASIMAGESINK" = "xyes")
 
-dnl use ext-gstreamer-audio -------------------------------------------------------------------
-AC_ARG_ENABLE(ext-gstreamer-audio, AC_HELP_STRING([--enable-ext-gstreamer-audio], [using gstreamer-audio]),
+dnl use evaspixmapsink ---------------------------------------------------------------------------
+AC_ARG_ENABLE(ext-evaspixmapsink, AC_HELP_STRING([--enable-ext-evaspixmapsink], [using evaspixmapsink]),
+  [
+    case "${enableval}" in
+      yes) GST_EXT_USE_EXT_EVASPIXMAPSINK=yes ;;
+      no)  GST_EXT_USE_EXT_EVASPIXMAPSINK=no ;;
+      *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ext-evaspixmapsink) ;;
+    esac
+  ],
+  [GST_EXT_USE_EXT_EVASPIXMAPSINK=yes])
+AM_CONDITIONAL(GST_EXT_USE_EXT_EVASPIXMAPSINK, test "x$GST_EXT_USE_EXT_EVASPIXMAPSINK" = "xyes")
+
+dnl use ext-xvimagesrc--------------------------------------------------------------------------
+AC_ARG_ENABLE(ext-xvimagesrc, AC_HELP_STRING([--enable-ext-xvimagesrc], [using xvimagesrc]),
   [
     case "${enableval}" in
-      yes) GST_EXT_USE_EXT_AVSYSAUDIO=yes ;;
-      no)  GST_EXT_USE_EXT_AVSYSAUDIO=no ;;
-      *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ext-gstreamer-audio) ;;
+      yes) GST_EXT_USE_EXT_XVIMAGESRC=yes ;;
+      no)  GST_EXT_USE_EXT_XVIMAGESRC=no ;;
+      *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ext-xvimagesrc) ;;
     esac
   ],
-  [GST_EXT_USE_EXT_AVSYSAUDIO=yes])
-AM_CONDITIONAL(GST_EXT_USE_EXT_AVSYSAUDIO, test "x$GST_EXT_USE_EXT_AVSYSAUDIO" = "xyes")
-
-if test "x$GST_EXT_USE_EXT_AVSYSAUDIO" = "xyes"; then
-       HAVE_AVSYSAUDIO=NO
-       PKG_CHECK_MODULES(AVSYSAUDIO, avsysaudio, HAVE_AVSYSAUDIO="yes", [
-           HAVE_AVSYSAUDIO="no"
-           AC_MSG_RESULT(no)
-         ])
-       if test "x$HAVE_AVSYSAUDIO" = "xno"; then
-         AC_MSG_ERROR(no avsysaudio package found)
-       fi
-       AC_SUBST(AVSYSAUDIO_CFLAGS)
-       AC_SUBST(AVSYSAUDIO_LIBS)
-fi     
+  [GST_EXT_USE_EXT_XVIMAGESRC=yes])
+AM_CONDITIONAL(GST_EXT_USE_EXT_XVIMAGESRC, test "x$GST_EXT_USE_EXT_XVIMAGESRC" = "xyes")
+
+AC_ARG_ENABLE(pcmdump, AC_HELP_STRING([--enable-pcmdump], [pcm dump]),
+  [
+    case "${enableval}" in
+      yes) PCM_DUMP_ENABLE=yes ;;
+      no)  PCM_DUMP_ENABLE=no ;;
+      *)   AC_MSG_ERROR(bad value ${enableval} for --enable-pcmdump) ;;
+    esac
+  ],
+  [PCM_DUMP_ENABLE=no])
+AM_CONDITIONAL([PCM_DUMP_ENABLE], [test "x$PCM_DUMP_ENABLE" = "xyes"])
 
 dnl use ext-drmsrc --------------------------------------------------------------------------
 AC_ARG_ENABLE(ext-drmsrc, AC_HELP_STRING([--enable-ext-drmsrc], [using drmsrc]),
@@ -258,6 +373,28 @@ 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_CLIENT, drm-client)
+       AC_SUBST(DRM_CLIENT_CFLAGS)
+       AC_SUBST(DRM_CLIENT_LIBS)
+       PKG_CHECK_MODULES(DRM_TRUSTED, drm-trusted)
+       AC_SUBST(DRM_TRUSTED_CFLAGS)
+       AC_SUBST(DRM_TRUSTED_LIBS)
+fi
+
+dnl use ext-submux --------------------------------------------------------------------------
+AC_ARG_ENABLE(ext-submux, AC_HELP_STRING([--enable-ext-submux], [using submux]),
+  [
+    case "${enableval}" in
+      yes) GST_EXT_USE_EXT_SUBMUX=yes ;;
+      no)  GST_EXT_USE_EXT_SUBMUX=no ;;
+      *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ext-submux) ;;
+    esac
+  ],
+  [GST_EXT_USE_EXT_SUBMUX=yes])
+AM_CONDITIONAL(GST_EXT_USE_EXT_SUBMUX, test "x$GST_EXT_USE_EXT_SUBMUX" = "xyes")
+
 dnl use ext-toggle --------------------------------------------------------------------------
 AC_ARG_ENABLE(ext-toggle, AC_HELP_STRING([--enable-ext-toggle], [using toggle]),
   [
@@ -305,6 +442,39 @@ AC_ARG_ENABLE(ext-audiotp, AC_HELP_STRING([--enable-ext-audiotp], [using audiotp
  [GST_EXT_USE_EXT_AUDIOTP=yes])
 AM_CONDITIONAL(GST_EXT_USE_EXT_AUDIOTP, test "x$GST_EXT_USE_EXT_AUDIOTP" = "xyes")
 
+dnl use ext-audioeq --------------------------------------------------------------------------
+AC_ARG_ENABLE(ext-audioeq, AC_HELP_STRING([--enable-ext-audioeq], [using audioeq]),
+[
+ case "${enableval}" in
+         yes) GST_EXT_USE_EXT_AUDIOEQ=yes ;;
+         no)  GST_EXT_USE_EXT_AUDIOEQ=no ;;
+         *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ext-audioeq) ;;
+ esac
+ ],
+ [GST_EXT_USE_EXT_AUDIOEQ=yes])
+AM_CONDITIONAL(GST_EXT_USE_EXT_AUDIOEQ, test "x$GST_EXT_USE_EXT_AUDIOEQ" = "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")
+
+#if test "x$GST_EXT_USE_EXT_PIFFDEMUX" = "xyes"; then
+#      PKG_CHECK_MODULES(DRM_CLIENT, drm-client)
+#      AC_SUBST(DRM_CLIENT_CFLAGS)
+#      AC_SUBST(DRM_CLIENT_LIBS)
+#      PKG_CHECK_MODULES(DRM_TRUSTED, drm-trusted)
+#      AC_SUBST(DRM_TRUSTED_CFLAGS)
+#      AC_SUBST(DRM_TRUSTED_LIBS)
+#fi
+
 dnl use ext-ssdemux --------------------------------------------------------------------------
 AC_ARG_ENABLE(ext-ssdemux, AC_HELP_STRING([--enable-ext-ssdemux], [using ssdemux]),
 [
@@ -317,25 +487,66 @@ AC_ARG_ENABLE(ext-ssdemux, AC_HELP_STRING([--enable-ext-ssdemux], [using ssdemux
  [GST_EXT_USE_EXT_SSDEMUX=yes])
 AM_CONDITIONAL(GST_EXT_USE_EXT_SSDEMUX, test "x$GST_EXT_USE_EXT_SSDEMUX" = "xyes")
 
+dnl use ext-dashdemux -----------------------------------------------------------------------
+AC_ARG_ENABLE(ext-dashdemux, AC_HELP_STRING([--enable-ext-dashdemux], [using dashdemux]),
+  [
+    case "${enableval}" in
+      yes) GST_EXT_USE_EXT_DASHDEMUX=yes ;;
+      no)  GST_EXT_USE_EXT_DASHDEMUX=no ;;
+      *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ext-dashdemux) ;;
+    esac
+  ],
+  [GST_EXT_USE_EXT_DASHDEMUX=yes])
+AM_CONDITIONAL(GST_EXT_USE_EXT_DASHDEMUX, test "x$GST_EXT_USE_EXT_DASHDEMUX" = "xyes")
+
+dnl use ext-hlsdemux2 -----------------------------------------------------------------------
+AC_ARG_ENABLE(ext-hlsdemux2, AC_HELP_STRING([--enable-ext-hlsdemux2], [using hlsdemux2]),
+  [
+    case "${enableval}" in
+      yes) GST_EXT_USE_EXT_HLSDEMUX2=yes ;;
+      no)  GST_EXT_USE_EXT_HLSDEMUX2=no ;;
+      *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ext-hlsdemux2) ;;
+    esac
+  ]
+  [GST_EXT_USE_EXT_HLSDEMUX2=yes])
+AM_CONDITIONAL(GST_EXT_USE_EXT_HLSDEMUX2, test "x$GST_EXT_USE_EXT_HLSDEMUX2" = "xyes")
+
+if test "x$GST_EXT_USE_EXT_HLSDEMUX2" = "xyes"; then                                                                       
+    dnl crypto for hlsdemux                                                                                                 
+    PKG_CHECK_MODULES(CRYPTO, libcrypto)                                                                                    
+    AC_SUBST(CRYPTO_CFLAGS)                                                                                                 
+    AC_SUBST(CRYPTO_LIBS)  
+fi
 
 AC_OUTPUT(
 Makefile
 common/Makefile
 common/m4/Makefile
-avsystem/Makefile
 pdpushsrc/Makefile
 pdpushsrc/src/Makefile
-avsystem/src/Makefile
 encodebin/Makefile
 encodebin/src/Makefile
 evasimagesink/Makefile
 evasimagesink/src/Makefile
+evaspixmapsink/Makefile
+xvimagesrc/Makefile
+xvimagesrc/src/Makefile
 toggle/Makefile
 toggle/src/Makefile
 drmsrc/Makefile
 drmsrc/src/Makefile
+submux/Makefile
+submux/src/Makefile
 audiotp/Makefile
 audiotp/src/Makefile
+audioeq/Makefile
+audioeq/src/Makefile
+piffdemux/Makefile
+piffdemux/src/Makefile
 ssdemux/Makefile
 ssdemux/src/Makefile
+dashdemux/Makefile
+dashdemux/src/Makefile
+hlsdemux2/Makefile
+hlsdemux2/src/Makefile
 )
diff --git a/dashdemux/Makefile.am b/dashdemux/Makefile.am
new file mode 100755 (executable)
index 0000000..308a09c
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = src\r
diff --git a/dashdemux/src/Makefile.am b/dashdemux/src/Makefile.am
new file mode 100644 (file)
index 0000000..643c7b2
--- /dev/null
@@ -0,0 +1,25 @@
+
+plugin_LTLIBRARIES = libgstdashdemux.la
+
+libgstdashdemux_la_SOURCES =                   \
+       gstmpdparser.c                          \
+       gstdashdemux.c                          \
+       gstfragment.c                           \
+       gsturidownloader.c                      \
+       gstdownloadrate.c                       \
+       gstplugin.c
+
+# headers we need but don't want installed
+noinst_HEADERS =             \
+        gstmpdparser.h                 \
+       gstfragmented.h                 \
+       gstfragment.h                   \
+       gstdashdemux.h                  \
+       gsturidownloader.h              \
+       gstdownloadrate.h
+
+# compiler and linker flags used to compile this plugin, set in configure.ac
+libgstdashdemux_la_CFLAGS = $(GST_CFLAGS) 
+libgstdashdemux_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS)
+libgstdashdemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstdashdemux_la_LIBTOOLFLAGS = --tag=disable-static
diff --git a/dashdemux/src/Makefile.in b/dashdemux/src/Makefile.in
new file mode 100644 (file)
index 0000000..7d81648
--- /dev/null
@@ -0,0 +1,605 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgstdashdemux_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libgstdashdemux_la_OBJECTS = libgstdashdemux_la-gstmpdparser.lo \
+       libgstdashdemux_la-gstdashdemux.lo \
+       libgstdashdemux_la-gstfragment.lo \
+       libgstdashdemux_la-gsturidownloader.lo \
+       libgstdashdemux_la-gstplugin.lo
+libgstdashdemux_la_OBJECTS = $(am_libgstdashdemux_la_OBJECTS)
+libgstdashdemux_la_LINK = $(LIBTOOL) --tag=CC \
+       $(libgstdashdemux_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
+       $(CCLD) $(libgstdashdemux_la_CFLAGS) $(CFLAGS) \
+       $(libgstdashdemux_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
+SOURCES = $(libgstdashdemux_la_SOURCES)
+DIST_SOURCES = $(libgstdashdemux_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+GST_CFLAGS = @GST_CFLAGS@
+GST_LIBS = @GST_LIBS@
+GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@
+HAVE_PKGCONFIG = @HAVE_PKGCONFIG@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libgstdashdemux.la
+libgstdashdemux_la_SOURCES = \
+       gstmpdparser.c                          \
+       gstdashdemux.c                          \
+       gstfragment.c                           \
+       gsturidownloader.c                      \
+       gstplugin.c
+
+
+# headers we need but don't want installed
+noinst_HEADERS = \
+        gstmpdparser.h                 \
+       gstfragmented.h                 \
+       gstfragment.h                   \
+       gstdashdemux.h                  \
+       gsturidownloader.h
+
+
+# compiler and linker flags used to compile this plugin, set in configure.ac
+libgstdashdemux_la_CFLAGS = $(GST_CFLAGS) 
+libgstdashdemux_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS)
+libgstdashdemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstdashdemux_la_LIBTOOLFLAGS = --tag=disable-static
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+       @$(NORMAL_INSTALL)
+       test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+       @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+       list2=; for p in $$list; do \
+         if test -f $$p; then \
+           list2="$$list2 $$p"; \
+         else :; fi; \
+       done; \
+       test -z "$$list2" || { \
+         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+       }
+
+uninstall-pluginLTLIBRARIES:
+       @$(NORMAL_UNINSTALL)
+       @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+       for p in $$list; do \
+         $(am__strip_dir) \
+         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+       done
+
+clean-pluginLTLIBRARIES:
+       -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+       @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+         test "$$dir" != "$$p" || dir=.; \
+         echo "rm -f \"$${dir}/so_locations\""; \
+         rm -f "$${dir}/so_locations"; \
+       done
+libgstdashdemux.la: $(libgstdashdemux_la_OBJECTS) $(libgstdashdemux_la_DEPENDENCIES) $(EXTRA_libgstdashdemux_la_DEPENDENCIES) 
+       $(libgstdashdemux_la_LINK) -rpath $(plugindir) $(libgstdashdemux_la_OBJECTS) $(libgstdashdemux_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstdashdemux_la-gstdashdemux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstdashdemux_la-gstfragment.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstdashdemux_la-gstmpdparser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstdashdemux_la-gstplugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstdashdemux_la-gsturidownloader.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LTCOMPILE) -c -o $@ $<
+
+libgstdashdemux_la-gstmpdparser.lo: gstmpdparser.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(libgstdashdemux_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdashdemux_la_CFLAGS) $(CFLAGS) -MT libgstdashdemux_la-gstmpdparser.lo -MD -MP -MF $(DEPDIR)/libgstdashdemux_la-gstmpdparser.Tpo -c -o libgstdashdemux_la-gstmpdparser.lo `test -f 'gstmpdparser.c' || echo '$(srcdir)/'`gstmpdparser.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/libgstdashdemux_la-gstmpdparser.Tpo $(DEPDIR)/libgstdashdemux_la-gstmpdparser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gstmpdparser.c' object='libgstdashdemux_la-gstmpdparser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(libgstdashdemux_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdashdemux_la_CFLAGS) $(CFLAGS) -c -o libgstdashdemux_la-gstmpdparser.lo `test -f 'gstmpdparser.c' || echo '$(srcdir)/'`gstmpdparser.c
+
+libgstdashdemux_la-gstdashdemux.lo: gstdashdemux.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(libgstdashdemux_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdashdemux_la_CFLAGS) $(CFLAGS) -MT libgstdashdemux_la-gstdashdemux.lo -MD -MP -MF $(DEPDIR)/libgstdashdemux_la-gstdashdemux.Tpo -c -o libgstdashdemux_la-gstdashdemux.lo `test -f 'gstdashdemux.c' || echo '$(srcdir)/'`gstdashdemux.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/libgstdashdemux_la-gstdashdemux.Tpo $(DEPDIR)/libgstdashdemux_la-gstdashdemux.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gstdashdemux.c' object='libgstdashdemux_la-gstdashdemux.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(libgstdashdemux_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdashdemux_la_CFLAGS) $(CFLAGS) -c -o libgstdashdemux_la-gstdashdemux.lo `test -f 'gstdashdemux.c' || echo '$(srcdir)/'`gstdashdemux.c
+
+libgstdashdemux_la-gstfragment.lo: gstfragment.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(libgstdashdemux_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdashdemux_la_CFLAGS) $(CFLAGS) -MT libgstdashdemux_la-gstfragment.lo -MD -MP -MF $(DEPDIR)/libgstdashdemux_la-gstfragment.Tpo -c -o libgstdashdemux_la-gstfragment.lo `test -f 'gstfragment.c' || echo '$(srcdir)/'`gstfragment.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/libgstdashdemux_la-gstfragment.Tpo $(DEPDIR)/libgstdashdemux_la-gstfragment.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gstfragment.c' object='libgstdashdemux_la-gstfragment.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(libgstdashdemux_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdashdemux_la_CFLAGS) $(CFLAGS) -c -o libgstdashdemux_la-gstfragment.lo `test -f 'gstfragment.c' || echo '$(srcdir)/'`gstfragment.c
+
+libgstdashdemux_la-gsturidownloader.lo: gsturidownloader.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(libgstdashdemux_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdashdemux_la_CFLAGS) $(CFLAGS) -MT libgstdashdemux_la-gsturidownloader.lo -MD -MP -MF $(DEPDIR)/libgstdashdemux_la-gsturidownloader.Tpo -c -o libgstdashdemux_la-gsturidownloader.lo `test -f 'gsturidownloader.c' || echo '$(srcdir)/'`gsturidownloader.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/libgstdashdemux_la-gsturidownloader.Tpo $(DEPDIR)/libgstdashdemux_la-gsturidownloader.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gsturidownloader.c' object='libgstdashdemux_la-gsturidownloader.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(libgstdashdemux_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdashdemux_la_CFLAGS) $(CFLAGS) -c -o libgstdashdemux_la-gsturidownloader.lo `test -f 'gsturidownloader.c' || echo '$(srcdir)/'`gsturidownloader.c
+
+libgstdashdemux_la-gstplugin.lo: gstplugin.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(libgstdashdemux_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdashdemux_la_CFLAGS) $(CFLAGS) -MT libgstdashdemux_la-gstplugin.lo -MD -MP -MF $(DEPDIR)/libgstdashdemux_la-gstplugin.Tpo -c -o libgstdashdemux_la-gstplugin.lo `test -f 'gstplugin.c' || echo '$(srcdir)/'`gstplugin.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/libgstdashdemux_la-gstplugin.Tpo $(DEPDIR)/libgstdashdemux_la-gstplugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='gstplugin.c' object='libgstdashdemux_la-gstplugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(libgstdashdemux_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdashdemux_la_CFLAGS) $(CFLAGS) -c -o libgstdashdemux_la-gstplugin.lo `test -f 'gstplugin.c' || echo '$(srcdir)/'`gstplugin.c
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       set x; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+       for dir in "$(DESTDIR)$(plugindir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+       mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+       clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+       distclean-compile distclean-generic distclean-libtool \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-pluginLTLIBRARIES \
+       install-ps install-ps-am install-strip installcheck \
+       installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/dashdemux/src/glibcompat.h b/dashdemux/src/glibcompat.h
new file mode 100755 (executable)
index 0000000..3f8951c
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+ * glibcompat.h\r
+ *\r
+ * Copyright (C) 2013 Douglas Gore <doug@ssonic.co.uk>\r
+ *\r
+ * Authors:\r
+ *   Douglas Gore <doug@ssonic.co.uk>\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
+#ifndef GLIBCOMPAT_H_\r
+#define GLIBCOMPAT_H_\r
+\r
+/* The GLib threading API changed in 2.32, these macros are used to\r
+ * provide backwards compatibility with older versions without\r
+ * complicating the code. */\r
+\r
+#include <glib.h>\r
+\r
+#if (GLIB_CHECK_VERSION (2, 32, 0))\r
+    #define G_MUTEX GMutex\r
+    #define G_MUTEX_INIT(mutex) g_mutex_init(&mutex)\r
+    #define G_MUTEX_CLEAR(mutex) g_mutex_clear (&mutex);\r
+    #define G_MUTEX_LOCK(mutex) g_mutex_lock (&mutex)\r
+    #define G_MUTEX_UNLOCK(mutex) g_mutex_unlock (&mutex)\r
+#else\r
+    #define G_MUTEX GMutex*\r
+    #define G_MUTEX_INIT(mutex) mutex = g_mutex_new()\r
+    #define G_MUTEX_CLEAR(mutex) g_mutex_free (mutex)\r
+    #define G_MUTEX_LOCK(mutex) g_mutex_lock (mutex)\r
+    #define G_MUTEX_UNLOCK(mutex) g_mutex_unlock (mutex)\r
+#endif\r
+\r
+#endif /* GLIBCOMPAT_H_ */\r
diff --git a/dashdemux/src/gstdashdemux.c b/dashdemux/src/gstdashdemux.c
new file mode 100755 (executable)
index 0000000..ba6fe2b
--- /dev/null
@@ -0,0 +1,1902 @@
+/*
+ * DASH demux plugin for GStreamer
+ *
+ * gstdashdemux.c
+ *
+ * Copyright (C) 2012 Orange
+ *
+ * Authors:
+ *   David Corvoysier <david.corvoysier@orange.com>
+ *   Hamid Zakari <hamid.zakari@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/**
+ * SECTION:element-dashdemux
+ *
+ * DASH demuxer element.
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch playbin2 uri="http://www-itec.uni-klu.ac.at/ftp/datasets/mmsys12/RedBullPlayStreets/redbull_4s/RedBullPlayStreets_4s_isoffmain_DIS_23009_1_v_2_1c2_2011_08_30.mpd"
+ * ]|
+ */
+
+/* Implementation notes:
+ *
+ * The following section describes how dashdemux works internally.
+ *
+ * Introduction:
+ *
+ * dashdemux is a "fake" demux, as unlike traditional demux elements, it
+ * doesn't split data streams contained in an enveloppe to expose them
+ * to downstream decoding elements.
+ *
+ * Instead, it parses an XML file called a manifest to identify a set of
+ * individual stream fragments it needs to fetch and expose to the actual
+ * demux elements that will handle them (this behavior is sometimes
+ * referred as the "demux after a demux" scenario).
+ *
+ * For a given section of content, several representations corresponding
+ * to different bitrates may be available: dashdemux will select the most
+ * appropriate representation based on local conditions (typically the
+ * available bandwidth and the amount of buffering available, capped by
+ * a maximum allowed bitrate).
+ *
+ * The representation selection algorithm can be configured using
+ * specific properties: max bitrate, min/max buffering, bandwidth ratio.
+ *
+ *
+ * General Design:
+ *
+ * dashdemux has a single sink pad that accepts the data corresponding
+ * to the manifest, typically fetched from an HTTP or file source.
+ *
+ * dashdemux exposes the streams it recreates based on the fragments it
+ * fetches through dedicated src pads corresponding to the caps of the
+ * fragments container (ISOBMFF/MP4 or MPEG2TS).
+ *
+ * During playback, new representations will typically be exposed as a
+ * new set of pads (see 'Switching between representations' below).
+ *
+ * Fragments downloading is performed using a dedicated task that fills
+ * an internal queue. Another task is in charge of popping fragments
+ * from the queue and pushing them downstream.
+ *
+ * Switching between representations:
+ *
+ * Decodebin supports scenarios allowing to seamlessly switch from one
+ * stream to another inside the same "decoding chain".
+ *
+ * To achieve that, it combines the elements it autoplugged in chains
+ *  and groups, allowing only one decoding group to be active at a given
+ * time for a given chain.
+ *
+ * A chain can signal decodebin that it is complete by sending a
+ * no-more-pads event, but even after that new pads can be added to
+ * create new subgroups, providing that a new no-more-pads event is sent.
+ *
+ * We take advantage of that to dynamically create a new decoding group
+ * in order to select a different representation during playback.
+ *
+ * Typically, assuming that each fragment contains both audio and video,
+ * the following tree would be created:
+ *
+ * chain "DASH Demux"
+ * |_ group "Representation set 1"
+ * |   |_ chain "Qt Demux 0"
+ * |       |_ group "Stream 0"
+ * |           |_ chain "H264"
+ * |           |_ chain "AAC"
+ * |_ group "Representation set 2"
+ *     |_ chain "Qt Demux 1"
+ *         |_ group "Stream 1"
+ *             |_ chain "H264"
+ *             |_ chain "AAC"
+ *
+ * Or, if audio and video are contained in separate fragments:
+ *
+ * chain "DASH Demux"
+ * |_ group "Representation set 1"
+ * |   |_ chain "Qt Demux 0"
+ * |   |   |_ group "Stream 0"
+ * |   |       |_ chain "H264"
+ * |   |_ chain "Qt Demux 1"
+ * |       |_ group "Stream 1"
+ * |           |_ chain "AAC"
+ * |_ group "Representation set 2"
+ *     |_ chain "Qt Demux 3"
+ *     |   |_ group "Stream 2"
+ *     |       |_ chain "H264"
+ *     |_ chain "Qt Demux 4"
+ *         |_ group "Stream 3"
+ *             |_ chain "AAC"
+ *
+ * In both cases, when switching from Set 1 to Set 2 an EOS is sent on
+ * each end pad corresponding to Rep 0, triggering the "drain" state to
+ * propagate upstream.
+ * Once both EOS have been processed, the "Set 1" group is completely
+ * drained, and decodebin2 will switch to the "Set 2" group.
+ *
+ * Note: nothing can be pushed to the new decoding group before the
+ * old one has been drained, which means that in order to be able to
+ * adapt quickly to bandwidth changes, we will not be able to rely
+ * on downstream buffering, and will instead manage an internal queue.
+ *
+ */
+
+#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 <inttypes.h>
+#include <gst/base/gsttypefindhelper.h>
+#include "gstdashdemux.h"
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src%d",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("application/dash+xml"));
+
+GST_DEBUG_CATEGORY_STATIC (gst_dash_demux_debug);
+#define GST_CAT_DEFAULT gst_dash_demux_debug
+
+enum
+{
+  PROP_0,
+
+  PROP_MAX_BUFFERING_TIME,
+  PROP_BANDWIDTH_USAGE,
+  PROP_MAX_BITRATE,
+  PROP_LAST
+};
+
+/* Default values for properties */
+#define DEFAULT_MAX_BUFFERING_TIME       30     /* in seconds */
+#define DEFAULT_BANDWIDTH_USAGE         0.8     /* 0 to 1     */
+#define DEFAULT_MAX_BITRATE        24000000     /* in bit/s  */
+
+#define DEFAULT_FAILED_COUNT 3
+#define DOWNLOAD_RATE_HISTORY_MAX 3
+#define DOWNLOAD_RATE_TIME_MAX 3 * GST_SECOND
+
+/* Custom internal event to signal end of period */
+#define GST_EVENT_DASH_EOP GST_EVENT_MAKE_TYPE(81, GST_EVENT_TYPE_DOWNSTREAM | GST_EVENT_TYPE_SERIALIZED)
+static GstEvent *
+gst_event_new_dash_eop (void)
+{
+  return gst_event_new_custom (GST_EVENT_DASH_EOP, NULL);
+}
+
+
+/* GObject */
+static void gst_dash_demux_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_dash_demux_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_dash_demux_dispose (GObject * obj);
+
+/* GstElement */
+static GstStateChangeReturn
+gst_dash_demux_change_state (GstElement * element, GstStateChange transition);
+
+/* GstDashDemux */
+static GstFlowReturn gst_dash_demux_pad (GstPad * pad, GstBuffer * buf);
+static gboolean gst_dash_demux_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_dash_demux_src_event (GstPad * pad, GstEvent * event);
+static gboolean gst_dash_demux_src_query (GstPad * pad, GstQuery * query);
+static void gst_dash_demux_stream_loop (GstDashDemux * demux);
+static void gst_dash_demux_download_loop (GstDashDemux * demux);
+static void gst_dash_demux_stop (GstDashDemux * demux);
+static void gst_dash_demux_resume_stream_task (GstDashDemux * demux);
+static void gst_dash_demux_resume_download_task (GstDashDemux * demux);
+static gboolean gst_dash_demux_setup_all_streams (GstDashDemux * demux);
+static gboolean gst_dash_demux_select_representations (GstDashDemux * demux);
+static GstCaps *gst_dash_demux_get_input_caps (GstDashDemux * demux, GstActiveStream * stream);
+static gboolean gst_dash_demux_get_next_fragment (GstDashDemux * demux, GstActiveStream **fragment_stream, GstClockTime *selected_ts);
+
+static void gst_dash_demux_clear_streams(GstDashDemux * demux);
+static void gst_dash_demux_reset (GstDashDemux * demux, gboolean dispose);
+static GstClockTime gst_dash_demux_get_buffering_time (GstDashDemux * demux);
+
+static void
+_do_init (GType type)
+{
+  GST_DEBUG_CATEGORY_INIT (gst_dash_demux_debug, "dashdemux", 0,
+      "dashdemux element");
+}
+
+GST_BOILERPLATE_FULL (GstDashDemux, gst_dash_demux, GstElement,
+    GST_TYPE_ELEMENT, _do_init);
+
+static void
+gst_dash_demux_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_static_pad_template (element_class, &srctemplate);
+
+  gst_element_class_add_static_pad_template (element_class, &sinktemplate);
+
+  gst_element_class_set_details_simple (element_class,
+      "DASH Demuxer",
+      "Codec/Demuxer",
+      "Dynamic Adaptive Streaming over HTTP demuxer",
+      "David Corvoysier <david.corvoysier@orange.com>\n\
+                Hamid Zakari <hamid.zakari@gmail.com>\n\
+                Gianluca Gennari <gennarone@gmail.com>");
+}
+
+static void
+gst_dash_demux_dispose (GObject * obj)
+{
+  GstDashDemux *demux = GST_DASH_DEMUX (obj);
+
+  if (demux->stream_task) {
+    if (GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED) {
+      GST_DEBUG_OBJECT (demux, "Leaving streaming task");
+      gst_task_stop (demux->stream_task);
+      gst_task_join (demux->stream_task);
+    }
+    gst_object_unref (demux->stream_task);
+    g_static_rec_mutex_free (&demux->stream_lock);
+    g_mutex_free(demux->stream_timed_lock);
+    demux->stream_task = NULL;
+  }
+
+  if (demux->download_task) {
+    if (GST_TASK_STATE (demux->download_task) != GST_TASK_STOPPED) {
+      GST_DEBUG_OBJECT (demux, "Leaving download task");
+      gst_task_stop (demux->download_task);
+      gst_task_join (demux->download_task);
+    }
+    gst_object_unref (demux->download_task);
+    g_static_rec_mutex_free (&demux->download_lock);
+    demux->download_task = NULL;
+  }
+
+  g_cond_clear (&demux->download_cond);
+  g_mutex_clear (&demux->download_mutex);
+
+  if (demux->downloader != NULL) {
+    g_object_unref (demux->downloader);
+    demux->downloader = NULL;
+  }
+
+  gst_dash_demux_reset (demux, TRUE);
+
+  G_OBJECT_CLASS (parent_class)->dispose (obj);
+}
+
+static void
+gst_dash_demux_class_init (GstDashDemuxClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  gobject_class->set_property = gst_dash_demux_set_property;
+  gobject_class->get_property = gst_dash_demux_get_property;
+  gobject_class->dispose = gst_dash_demux_dispose;
+
+  g_object_class_install_property (gobject_class, PROP_MAX_BUFFERING_TIME,
+      g_param_spec_uint ("max-buffering-time", "Maximum buffering time",
+          "Maximum number of seconds of buffer accumulated during playback",
+          2, G_MAXUINT, DEFAULT_MAX_BUFFERING_TIME,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_BANDWIDTH_USAGE,
+      g_param_spec_float ("bandwidth-usage",
+          "Bandwidth usage [0..1]",
+          "Percentage of the available bandwidth to use when selecting representations",
+          0, 1, DEFAULT_BANDWIDTH_USAGE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_MAX_BITRATE,
+      g_param_spec_uint ("max-bitrate", "Max bitrate",
+          "Max of bitrate supported by target decoder",
+          1000, G_MAXUINT, DEFAULT_MAX_BITRATE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_dash_demux_change_state);
+}
+
+static gboolean
+_check_queue_full (GstDataQueue * q, guint visible, guint bytes, guint64 time,
+    GstDashDemux *demux)
+{
+  return time > demux->max_buffering_time;
+}
+
+static void
+_data_queue_item_destroy (GstDataQueueItem * item)
+{
+  gst_mini_object_unref (item->object);
+  g_free (item);
+}
+
+static void
+gst_dash_demux_stream_push_event (GstDashDemuxStream * stream,
+                                  GstEvent *event)
+{
+  GstDataQueueItem *item = g_new0 (GstDataQueueItem, 1);
+
+  item->object = GST_MINI_OBJECT_CAST (event);
+  item->destroy = (GDestroyNotify) _data_queue_item_destroy;
+
+  gst_data_queue_push (stream->queue, item);
+}
+
+static void
+gst_dash_demux_stream_push_data (GstDashDemuxStream * stream,
+    GstBuffer * buffer)
+{
+  GstDataQueueItem *item = g_new0 (GstDataQueueItem, 1);
+
+  item->object = GST_MINI_OBJECT_CAST (buffer);
+  item->duration = GST_BUFFER_DURATION (buffer);
+  item->visible = TRUE;
+  item->size = GST_BUFFER_SIZE (buffer);
+
+  item->destroy = (GDestroyNotify) _data_queue_item_destroy;
+
+  gst_data_queue_push (stream->queue, item);
+}
+
+static void
+gst_dash_demux_init (GstDashDemux * demux, GstDashDemuxClass * klass)
+{
+  /* sink pad */
+  demux->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
+  gst_pad_set_chain_function (demux->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_dash_demux_pad));
+  gst_pad_set_event_function (demux->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_dash_demux_sink_event));
+  gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
+
+  /* Downloader */
+  demux->downloader = gst_uri_downloader_new ();
+
+  /* Properties */
+  demux->max_buffering_time = DEFAULT_MAX_BUFFERING_TIME * GST_SECOND;
+  demux->bandwidth_usage = DEFAULT_BANDWIDTH_USAGE;
+  demux->max_bitrate = DEFAULT_MAX_BITRATE;
+
+  demux->max_video_width = 0;
+  demux->max_video_height = 0;
+
+  /* Updates task */
+  g_static_rec_mutex_init (&demux->download_lock);
+  demux->download_task =
+      gst_task_create ((GstTaskFunction) gst_dash_demux_download_loop, demux);
+  gst_task_set_lock (demux->download_task, &demux->download_lock);
+  g_cond_init (&demux->download_cond);
+  g_mutex_init (&demux->download_mutex);
+
+  /* Streaming task */
+  g_static_rec_mutex_init (&demux->stream_lock);
+  demux->stream_task =
+      gst_task_create ((GstTaskFunction) gst_dash_demux_stream_loop, demux);
+  gst_task_set_lock (demux->stream_task, &demux->stream_lock);
+  demux->stream_timed_lock = g_mutex_new ();
+}
+
+static void
+gst_dash_demux_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstDashDemux *demux = GST_DASH_DEMUX (object);
+
+  switch (prop_id) {
+    case PROP_MAX_BUFFERING_TIME:
+      demux->max_buffering_time = g_value_get_uint (value) * GST_SECOND;
+      break;
+    case PROP_BANDWIDTH_USAGE:
+      demux->bandwidth_usage = g_value_get_float (value);
+      break;
+    case PROP_MAX_BITRATE:
+      demux->max_bitrate = g_value_get_uint (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_dash_demux_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstDashDemux *demux = GST_DASH_DEMUX (object);
+
+  switch (prop_id) {
+    case PROP_MAX_BUFFERING_TIME:
+      g_value_set_uint (value, demux->max_buffering_time / GST_SECOND);
+      break;
+    case PROP_BANDWIDTH_USAGE:
+      g_value_set_float (value, demux->bandwidth_usage);
+      break;
+    case PROP_MAX_BITRATE:
+      g_value_set_uint (value, demux->max_bitrate);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static GstStateChangeReturn
+gst_dash_demux_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret;
+  GstDashDemux *demux = GST_DASH_DEMUX (element);
+
+  GST_DEBUG_OBJECT (demux, "changing state %s - %s",
+      gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
+      gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      gst_dash_demux_reset (demux, FALSE);
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      demux->cancelled = TRUE;
+      gst_dash_demux_stop (demux);
+      gst_task_join (demux->stream_task);
+      gst_task_join (demux->download_task);
+      break;
+    default:
+      break;
+  }
+  return ret;
+}
+
+void
+gst_dash_demux_flush_stream_queues (GstDashDemux * demux)
+{
+  GSList *it;
+  GstDashDemuxStream *stream;
+  for(it = demux->streams; it; it=it->next)
+  {
+    stream = it->data;
+    gst_data_queue_set_flushing(stream->queue, TRUE);
+    gst_data_queue_flush(stream->queue);
+  }
+}
+
+static gboolean
+gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
+{
+  GstDashDemux *demux;
+
+  demux = GST_DASH_DEMUX (gst_pad_get_element_private (pad));
+
+  switch (event->type) {
+    case GST_EVENT_SEEK:
+    {
+      gdouble rate;
+      GstFormat format;
+      GstSeekFlags flags;
+      GstSeekType start_type, stop_type;
+      gint64 start, stop;
+      GList *list;
+      GstClockTime current_pos = GST_CLOCK_TIME_NONE;
+      GstClockTime target_pos;
+      guint current_period;
+      GstActiveStream *stream;
+      GstStreamPeriod *period = NULL;
+      guint nb_active_stream;
+      guint stream_idx = 0;
+      guint *seek_idx = NULL;   /*Seek positions on each stream*/
+      gboolean end_of_mpd = FALSE;
+
+      if (gst_mpd_client_is_live (demux->client)) {
+        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)
+        return FALSE;
+
+      GST_DEBUG_OBJECT (demux,
+          "seek event, rate: %f type: %d start: %" GST_TIME_FORMAT " stop: %"
+          GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start),
+          GST_TIME_ARGS (stop));
+
+      //GST_MPD_CLIENT_LOCK (demux->client);
+
+      /* select the requested Period in the Media Presentation */
+      target_pos = (GstClockTime) start;
+      current_period = 0;
+      for (list = g_list_first (demux->client->periods); list;
+          list = g_list_next (list)) {
+        period = list->data;
+        current_pos = period->start;
+        current_period = period->number;
+        if (current_pos <= target_pos
+            && target_pos < current_pos + period->duration) {
+          break;
+        }
+      }
+      if(target_pos == current_pos + period->duration) {
+        /*Seeking to the end of MPD*/
+        end_of_mpd = TRUE;
+        goto seeking;
+      }
+      if (list == NULL) {
+        GST_WARNING_OBJECT (demux, "Could not find seeked Period");
+        return FALSE;
+      }
+      if (current_period != gst_mpd_client_get_period_index (demux->client)) {
+        GST_DEBUG_OBJECT (demux, "Seeking to Period %d", current_period);
+        /* setup video, audio and subtitle streams, starting from the new Period */
+        if (!gst_mpd_client_set_period_index (demux->client, current_period) ||
+            !gst_dash_demux_setup_all_streams (demux))
+          return FALSE;
+      }
+
+      /*select the requested segments for all streams*/
+      nb_active_stream = gst_mpdparser_get_nb_active_stream (demux->client);
+      seek_idx = g_malloc0(sizeof(gint)*nb_active_stream);
+      gint video_idx = gst_mpd_client_get_video_active_stream_id(demux->client);
+      if(video_idx >= 0) {
+        /*Seeking on video stream firstly.*/
+        GstClockTime segment_start;
+        segment_start = gst_mpd_client_stream_find_segment(demux->client, video_idx,
+                                                         target_pos, &seek_idx[video_idx]);
+        if(!GST_CLOCK_TIME_IS_VALID(segment_start))
+          goto no_segment;
+        target_pos = segment_start;
+      }
+      /*Seeking on non video streams*/
+      for (stream_idx = 0; stream_idx < nb_active_stream; stream_idx++) {
+        if (video_idx != stream_idx) {
+          GstClockTime stream_start = gst_mpd_client_stream_find_segment(demux->client,
+                                          stream_idx, target_pos, &seek_idx[stream_idx]);
+          if(!GST_CLOCK_TIME_IS_VALID (stream_start)) {
+            goto no_segment;
+          }
+        }
+      }
+
+seeking:
+      /* We can actually perform the seek */
+      nb_active_stream = gst_mpdparser_get_nb_active_stream (demux->client);
+
+      if (flags & GST_SEEK_FLAG_FLUSH) {
+        GST_DEBUG_OBJECT (demux, "sending flush start");
+        stream_idx = 0;
+        while (stream_idx < nb_active_stream) {
+          GstDashDemuxStream *dash_stream = g_slist_nth_data (demux->streams, stream_idx);
+         dash_stream->need_header = TRUE;
+          gst_pad_push_event (dash_stream->srcpad,
+              gst_event_new_flush_start ());
+          stream_idx++;
+        }
+      }
+
+      /* Stop the demux */
+      demux->cancelled = TRUE;
+      gst_dash_demux_stop (demux);
+      GST_DEBUG_OBJECT (demux, "joining tasks");
+      gst_task_join (demux->stream_task);
+      gst_task_join (demux->download_task);
+      GST_DEBUG_OBJECT (demux, "tasks was joined");
+
+      /* Wait for streaming to finish */
+      g_static_rec_mutex_lock (&demux->stream_lock);
+
+      //GST_MPD_CLIENT_LOCK (demux->client);
+      demux->end_of_period = end_of_mpd;
+      //GST_MPD_CLIENT_UNLOCK (demux->client);
+
+
+      for (stream_idx = 0; stream_idx < nb_active_stream; stream_idx++) {
+        GstDashDemuxStream *dash_stream = g_slist_nth_data (demux->streams, stream_idx);
+        GstCaps *caps = gst_pad_get_negotiated_caps (dash_stream->srcpad);
+        if(caps) {
+          gst_caps_replace (&dash_stream->input_caps, NULL);
+          gst_caps_unref (caps);
+        }
+        if(!end_of_mpd) {
+          GST_DEBUG_OBJECT (demux, "Seeking to sequence %d on stream %d", seek_idx[stream_idx], stream_idx);
+          stream = gst_mpdparser_get_active_stream_by_index (demux->client, stream_idx);
+          gst_mpd_client_set_segment_index(stream, seek_idx[stream_idx]);
+        }
+        gst_data_queue_set_flushing(dash_stream->queue, FALSE);
+        dash_stream->start_time = target_pos;
+        dash_stream->download_end_of_period = end_of_mpd;
+        dash_stream->stream_end_of_period = end_of_mpd;
+        dash_stream->stream_eos = end_of_mpd;
+        dash_stream->need_segment = TRUE;
+      }
+      if(!end_of_mpd)
+        g_free(seek_idx);
+
+      if (flags & GST_SEEK_FLAG_FLUSH) {
+        GST_DEBUG_OBJECT (demux, "Sending flush stop on all pad");
+
+        for (stream_idx = 0; stream_idx < nb_active_stream; stream_idx++) {
+          GstDashDemuxStream *dash_stream = g_slist_nth_data (demux->streams, stream_idx);
+          gst_pad_push_event (dash_stream->srcpad,
+              gst_event_new_flush_stop ());
+        }
+      }
+
+      /* Restart the demux */
+      demux->cancelled = FALSE;
+      gst_dash_demux_resume_download_task (demux);
+      gst_dash_demux_resume_stream_task (demux);
+      g_static_rec_mutex_unlock (&demux->stream_lock);
+
+      return TRUE;
+no_segment:
+      {
+        GST_WARNING_OBJECT (demux, "Could not find seeked fragment on stream %d", stream_idx);
+        g_free(seek_idx);
+        return FALSE;
+      }
+    }
+    default:
+      break;
+  }
+
+  return gst_pad_event_default (pad, event);
+}
+
+static gboolean
+gst_dash_demux_setup_mpdparser_streams (GstDashDemux * demux, GstMpdClient *client)
+{
+  GList *listLang = NULL;
+  guint i, nb_audio;
+  gchar *lang;
+
+  GST_MPD_CLIENT_LOCK (client);
+  /* clean old active stream list, if any */
+  gst_active_streams_free (client);
+
+  if (!gst_mpd_client_setup_streaming (client, GST_STREAM_VIDEO, "")) {
+    GST_INFO_OBJECT (demux, "No video adaptation set found");
+  } else {
+    gst_mpd_client_get_max_video_dimensions(client, &demux->max_video_width,
+                                            &demux->max_video_height);
+  }
+
+  nb_audio =
+      gst_mpdparser_get_list_and_nb_of_audio_language (client,
+      &listLang);
+  if (nb_audio == 0)
+    nb_audio = 1;
+  GST_INFO_OBJECT (demux, "Number of language is=%d", nb_audio);
+
+  for (i = 0; i < nb_audio; i++) {
+    lang = (gchar *) g_list_nth_data (listLang, i);
+    if (gst_mpdparser_get_nb_adaptationSet (client) > 1)
+      if (!gst_mpd_client_setup_streaming (client, GST_STREAM_AUDIO,
+              lang))
+        GST_INFO_OBJECT (demux, "No audio adaptation set found");
+
+    if (gst_mpdparser_get_nb_adaptationSet (client) > nb_audio)
+      if (!gst_mpd_client_setup_streaming (client,
+              GST_STREAM_APPLICATION, lang))
+        GST_INFO_OBJECT (demux, "No application adaptation set found");
+  }
+  GST_MPD_CLIENT_UNLOCK (client);
+  return TRUE;
+}
+
+static gboolean
+gst_dash_demux_setup_all_streams (GstDashDemux * demux)
+{
+  guint i;
+  if( !gst_dash_demux_setup_mpdparser_streams(demux, demux->client))
+    return FALSE;
+
+  GST_DEBUG_OBJECT (demux, "Creating dashdemux streams");
+  gst_dash_demux_clear_streams(demux);
+  for ( i =0; i < gst_mpdparser_get_nb_active_stream (demux->client); i++) {
+    GstDashDemuxStream *dash_stream;
+    GstCaps *caps;
+    GstActiveStream *active_stream;
+    dash_stream = g_new0(GstDashDemuxStream, 1);
+    demux->streams = g_slist_append(demux->streams, dash_stream);
+    dash_stream->idx = i;
+    dash_stream->queue = gst_data_queue_new ((GstDataQueueCheckFullFunction) _check_queue_full, demux);
+    dash_stream->need_header = TRUE;
+    dash_stream->need_segment = TRUE;
+    dash_stream->start_time = GST_CLOCK_TIME_NONE;
+    gst_download_rate_init (&dash_stream->dnl_rate);
+    gst_download_rate_set_max_length (&dash_stream->dnl_rate,
+                                     DOWNLOAD_RATE_HISTORY_MAX);
+    gst_download_rate_set_aver_period (&dash_stream->dnl_rate,
+                                      DOWNLOAD_RATE_TIME_MAX);
+    /*Create stream pad*/
+    active_stream = gst_mpdparser_get_active_stream_by_index(demux->client, i);
+    caps = gst_dash_demux_get_input_caps(demux, active_stream);
+    dash_stream->srcpad = gst_pad_new_from_static_template (&srctemplate, NULL);
+    gst_pad_set_event_function (dash_stream->srcpad,
+        GST_DEBUG_FUNCPTR (gst_dash_demux_src_event));
+    gst_pad_set_query_function (dash_stream->srcpad,
+        GST_DEBUG_FUNCPTR (gst_dash_demux_src_query));
+    gst_pad_set_element_private (dash_stream->srcpad, demux);
+    gst_pad_set_active (dash_stream->srcpad, TRUE);
+    gst_pad_set_caps (dash_stream->srcpad, caps);
+    gst_caps_unref(caps);
+    gst_element_add_pad (GST_ELEMENT (demux), gst_object_ref (dash_stream->srcpad));
+  }
+  /* Send 'no-more-pads' to have decodebin create the new group */
+  gst_element_no_more_pads (GST_ELEMENT (demux));
+
+  return TRUE;
+}
+
+static gboolean
+gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
+{
+  GstDashDemux *demux = GST_DASH_DEMUX (gst_pad_get_parent (pad));
+
+  switch (event->type) {
+    case GST_EVENT_EOS:{
+      gchar *manifest;
+      GstQuery *query;
+      gboolean res;
+
+      if (demux->manifest == NULL) {
+        GST_WARNING_OBJECT (demux, "Received EOS without a manifest.");
+        break;
+      }
+
+      GST_DEBUG_OBJECT (demux, "Got EOS on the sink pad: manifest fetched");
+
+      if (demux->client)
+        gst_mpd_client_free (demux->client);
+      demux->client = gst_mpd_client_new ();
+
+      query = gst_query_new_uri ();
+      res = gst_pad_peer_query (pad, query);
+      if (res) {
+        gst_query_parse_uri (query, &demux->client->mpd_uri);
+        GST_DEBUG_OBJECT (demux, "Fetched MPD file at URI: %s",
+            demux->client->mpd_uri);
+      } else {
+        GST_WARNING_OBJECT (demux, "MPD URI query failed.");
+      }
+      gst_query_unref (query);
+
+      manifest = (gchar *) GST_BUFFER_DATA (demux->manifest);
+      if (manifest == NULL) {
+        GST_WARNING_OBJECT (demux, "Error validating the manifest.");
+      } else if (!gst_mpd_parse (demux->client, 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 manifest */
+        GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid manifest."),
+            (NULL));
+        return FALSE;
+      }
+
+      gst_buffer_unref (demux->manifest);
+      demux->manifest = NULL;
+
+      if (!gst_mpd_client_setup_media_presentation (demux->client)) {
+        GST_ELEMENT_ERROR (demux, STREAM, DECODE,
+            ("Incompatible manifest file."), (NULL));
+        return FALSE;
+      }
+
+      /* setup video, audio and subtitle streams, starting from first Period */
+      if (!gst_mpd_client_set_period_index (demux->client, 0) ||
+          !gst_dash_demux_setup_all_streams (demux))
+        return FALSE;
+
+      /* start playing from the first segment */
+      gst_mpd_client_set_segment_index_for_all_streams (demux->client, 0);
+
+      /* Send duration message */
+      if (!gst_mpd_client_is_live (demux->client)) {
+        GstClockTime duration =
+            gst_mpd_client_get_media_presentation_duration (demux->client);
+
+        if (duration != GST_CLOCK_TIME_NONE) {
+          GST_DEBUG_OBJECT (demux,
+              "Sending duration message : %" GST_TIME_FORMAT,
+              GST_TIME_ARGS (duration));
+          gst_element_post_message (GST_ELEMENT (demux),
+              gst_message_new_duration (GST_OBJECT (demux), GST_FORMAT_TIME,
+                  duration));
+        } else {
+          GST_DEBUG_OBJECT (demux,
+              "mediaPresentationDuration unknown, can not send the duration message");
+        }
+      }
+      gst_dash_demux_resume_download_task (demux);
+      gst_dash_demux_resume_stream_task (demux);
+      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_dash_demux_src_query (GstPad * pad, GstQuery * query)
+{
+  GstDashDemux *dashdemux;
+  gboolean ret = FALSE;
+
+  if (query == NULL)
+    return FALSE;
+
+  dashdemux = GST_DASH_DEMUX (gst_pad_get_element_private (pad));
+
+  switch (query->type) {
+    case GST_QUERY_DURATION:{
+      GstClockTime duration = -1;
+      GstFormat fmt;
+
+      gst_query_parse_duration (query, &fmt, NULL);
+      if (fmt == GST_FORMAT_TIME) {
+        duration =
+            gst_mpd_client_get_media_presentation_duration (dashdemux->client);
+        if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0) {
+          gst_query_set_duration (query, GST_FORMAT_TIME, duration);
+          ret = TRUE;
+        }
+      }
+      GST_DEBUG_OBJECT (dashdemux,
+          "GST_QUERY_DURATION returns %s with duration %" GST_TIME_FORMAT,
+          ret ? "TRUE" : "FALSE", GST_TIME_ARGS (duration));
+      break;
+    }
+    case GST_QUERY_SEEKING:{
+      GstFormat fmt;
+      gint64 stop = -1;
+
+      gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
+      GST_DEBUG_OBJECT (dashdemux, "Received GST_QUERY_SEEKING with format %d",
+          fmt);
+      if (fmt == GST_FORMAT_TIME) {
+        GstClockTime duration;
+
+        duration =
+            gst_mpd_client_get_media_presentation_duration (dashdemux->client);
+        if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0)
+          stop = duration;
+
+        gst_query_set_seeking (query, fmt,
+            !gst_mpd_client_is_live (dashdemux->client), 0, stop);
+        ret = TRUE;
+        GST_DEBUG_OBJECT (dashdemux, "GST_QUERY_SEEKING returning with stop : %"
+            GST_TIME_FORMAT, GST_TIME_ARGS (stop));
+      }
+      break;
+    }
+    case GST_QUERY_URI: {
+      /* forwarding uri */
+      GST_DEBUG("URI query recevied in DASH demux.....");
+        gboolean res;
+        res = gst_pad_query_default (pad,query);
+        if(res)
+          GST_DEBUG("forwarding URI is done successfully!!...");
+      ret = TRUE;
+      break;
+    }
+    default:{
+      // By default, do not forward queries upstream
+      break;
+    }
+  }
+
+  return ret;
+}
+
+static GstFlowReturn
+gst_dash_demux_pad (GstPad * pad, GstBuffer * buf)
+{
+  GstDashDemux *demux = GST_DASH_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 void
+gst_dash_demux_stop (GstDashDemux * demux)
+{
+  gst_uri_downloader_cancel (demux->downloader);
+  gst_dash_demux_flush_stream_queues (demux);
+
+  if (GST_TASK_STATE (demux->download_task) != GST_TASK_STOPPED) {
+    GST_TASK_SIGNAL (demux->download_task);
+    gst_task_stop (demux->download_task);
+    g_mutex_lock (&demux->download_mutex);
+    g_cond_signal (&demux->download_cond);
+    g_mutex_unlock (&demux->download_mutex);
+  }
+  if (GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED) {
+    GST_TASK_SIGNAL (demux->stream_task);
+    gst_task_stop (demux->stream_task);
+  }
+}
+
+/* gst_dash_demux_stream_loop:
+ *
+ * Loop for the "stream' task that pushes fragments to the src pads.
+ *
+ * Startup:
+ * The task is started as soon as we have received the manifest and
+ * waits for the first fragment to be downloaded and pushed in the
+ * queue. Once this fragment has been pushed, the task pauses itself
+ * until actual playback begins.
+ *
+ * During playback:
+ * The task pushes fragments downstream at regular intervals based on
+ * the fragment duration. If it detects a queue underrun, it sends
+ * a buffering event to tell the main application to pause.
+ *
+ * Teardown:
+ * The task is stopped when we have reached the end of the manifest
+ * and emptied our queue.
+ *
+ */
+static void
+gst_dash_demux_stream_loop (GstDashDemux * demux)
+{
+  GstFlowReturn ret;
+  GstActiveStream *active_stream;
+  GstDashDemuxStream *selected_stream = NULL;
+  GstClockTime min_ts = GST_CLOCK_TIME_NONE;
+  guint i = 0;
+  gboolean eos = TRUE;
+  gboolean eop = TRUE;
+
+  for (i = 0; i < g_slist_length (demux->streams); i++) {
+    GstDashDemuxStream *dash_stream = g_slist_nth_data (demux->streams, i);
+    GstBuffer *buffer;
+    GstDataQueueItem *item;
+
+    if (dash_stream->stream_eos) {
+      GST_DEBUG_OBJECT (demux, "Stream %d is eos, skipping", dash_stream->idx);
+      continue;
+    }
+
+    if (dash_stream->stream_end_of_period) {
+      GST_DEBUG_OBJECT (demux, "Stream %d is eop, skipping", dash_stream->idx);
+      eos = FALSE;
+      continue;
+    }
+    eos = FALSE;
+    eop = FALSE;
+
+    if (!gst_data_queue_peek (dash_stream->queue, &item))
+      goto flushing;
+
+    if(GST_IS_BUFFER(item->object)) {
+      buffer = GST_BUFFER(item->object);
+      if(GST_BUFFER_TIMESTAMP(buffer) < min_ts ||
+         !GST_CLOCK_TIME_IS_VALID(min_ts)) {
+        min_ts = GST_BUFFER_TIMESTAMP(buffer);
+        selected_stream = dash_stream;
+      } else if (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (item->object))) {
+        selected_stream = dash_stream;
+        break;
+      }
+    } else {
+      selected_stream = dash_stream;
+      break;
+    }
+  }
+
+  if(selected_stream) {
+    GstBuffer *buffer;
+    GstDataQueueItem *item;
+
+    if (!gst_data_queue_pop (selected_stream->queue, &item))
+      goto end;
+    if ( GST_IS_BUFFER (item->object)) {
+      buffer = GST_BUFFER(item->object);
+      active_stream = gst_mpdparser_get_active_stream_by_index (demux->client, selected_stream->idx);
+
+      if (selected_stream->need_segment) {
+        if(!GST_CLOCK_TIME_IS_VALID (selected_stream->start_time)) {
+          if(GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))){
+            selected_stream->start_time = GST_BUFFER_TIMESTAMP (buffer);
+          } else {
+            selected_stream->start_time = 0;
+          }
+        }
+        /* And send a newsegment */
+        GST_DEBUG_OBJECT (demux, "Sending new-segment stream #%d. segment start:%"
+            GST_TIME_FORMAT, selected_stream->idx, GST_TIME_ARGS (selected_stream->start_time));
+        gst_pad_push_event (selected_stream->srcpad,
+            gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+                selected_stream->start_time, GST_CLOCK_TIME_NONE, selected_stream->start_time));
+        selected_stream->need_segment = FALSE;
+      }
+
+      GST_DEBUG_OBJECT (demux, "Pushing fragment #%llu (stream %d) ts=%"GST_TIME_FORMAT, GST_BUFFER_OFFSET (buffer),
+                        selected_stream->idx, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
+      ret = gst_pad_push (selected_stream->srcpad, gst_buffer_ref(buffer) );
+      item->destroy (item);
+      if ((ret != GST_FLOW_OK) && (active_stream->mimeType == GST_STREAM_VIDEO))
+        goto error_pushing;
+    } else {
+      GstEvent *event = GST_EVENT (item->object);
+      if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
+        selected_stream->stream_eos = TRUE;
+        selected_stream->stream_end_of_period = TRUE;
+      } else if (GST_EVENT_TYPE (event) == GST_EVENT_DASH_EOP) {
+        selected_stream->stream_end_of_period = TRUE;
+      }
+
+      if (GST_EVENT_TYPE (item->object) != GST_EVENT_DASH_EOP) {
+        gst_pad_push_event (selected_stream->srcpad,
+            gst_event_ref (GST_EVENT_CAST (item->object)));
+      }
+
+      item->destroy (item);
+    }
+  } else {
+    if (eos) {
+      goto end_of_manifest;
+    } else if (eop) {
+      /*TODO Switch to next period*/
+    }
+  }
+
+end:
+  return;
+
+flushing:
+  {
+    GST_INFO_OBJECT (demux, "Queue is flushing. Stopped streaming task");
+    gst_task_stop (demux->stream_task);
+    return;
+  }
+
+end_of_manifest:
+  {
+    GST_INFO_OBJECT (demux, "Reached end of manifest, sending EOS");
+    guint i = 0;
+    for (i = 0; i < gst_mpdparser_get_nb_active_stream (demux->client); i++) {
+      GstDashDemuxStream *dash_stream = g_slist_nth_data (demux->streams, i);
+      gst_pad_push_event (dash_stream->srcpad, gst_event_new_eos ());
+    }
+    GST_INFO_OBJECT (demux, "Stopped streaming task");
+    gst_task_stop (demux->stream_task);
+    return;
+  }
+
+error_pushing:
+  {
+    /* FIXME: handle error */
+    GST_ERROR_OBJECT (demux,
+        "Error pushing buffer: %s... terminating the demux",
+        gst_flow_get_name (ret));
+    gst_dash_demux_stop (demux);
+    return;
+  }
+}
+
+static void
+gst_dash_demux_clear_streams(GstDashDemux * demux) {
+  guint i = 0;
+  gst_dash_demux_flush_stream_queues (demux);
+  for (i = 0; i < g_slist_length(demux->streams); i++) {
+    GstDashDemuxStream *dash_stream = g_slist_nth_data (demux->streams, i);
+    gst_download_rate_deinit (&dash_stream->dnl_rate);
+    if (dash_stream->input_caps) {
+      gst_caps_unref (dash_stream->input_caps);
+      dash_stream->input_caps = NULL;
+    }
+    if (dash_stream->srcpad) {
+      gst_object_unref (dash_stream->srcpad);
+      dash_stream->srcpad = NULL;
+    }
+    /*TODO consider unref stream->output_caps*/
+    g_object_unref (dash_stream->queue);
+  }
+  if(demux->streams) {
+    g_slist_free(demux->streams);
+    demux->streams = NULL;
+  }
+}
+
+static void
+gst_dash_demux_reset (GstDashDemux * demux, gboolean dispose)
+{
+  gint stream_idx;
+  demux->end_of_period = FALSE;
+  demux->cancelled = FALSE;
+
+  gst_dash_demux_clear_streams(demux);
+
+  if (demux->manifest) {
+    gst_buffer_unref (demux->manifest);
+    demux->manifest = NULL;
+  }
+  if (demux->client) {
+    gst_mpd_client_free (demux->client);
+    demux->client = NULL;
+  }
+  if (!dispose) {
+    demux->client = gst_mpd_client_new ();
+  }
+
+  demux->last_manifest_update = GST_CLOCK_TIME_NONE;
+  for (stream_idx = 0; stream_idx < g_slist_length (demux->streams); stream_idx++) {
+    GstDashDemuxStream *dash_stream = g_slist_nth_data (demux->streams, stream_idx);
+    dash_stream->need_segment = TRUE;
+  }
+}
+
+static GstClockTime
+gst_dash_demux_get_buffering_time (GstDashDemux * demux)
+{
+  GstClockTime buffer_time = 0;
+  GSList *it;
+  GstDashDemuxStream *stream;
+  GstDataQueueSize queue_size;
+
+  for(it=demux->streams; it; it=it->next) {
+    stream = it->data;
+    gst_data_queue_get_level(stream->queue, &queue_size);
+
+    if (queue_size.time > 0) {
+      buffer_time = queue_size.time;
+      break;
+    }
+  }
+
+  return buffer_time;
+}
+
+static gboolean
+gst_dash_demux_update_manifest(GstDashDemux *demux) {
+  GstFragment *download;
+  GstBuffer *buffer;
+  GstClockTime duration, now = gst_util_get_timestamp();
+  gint64 update_period = demux->client->mpd_node->minimumUpdatePeriod;
+
+  if (update_period == -1) {
+    GST_DEBUG_OBJECT (demux, "minimumUpdatePeriod unspecified, will not update MPD");
+    return TRUE;
+  }
+
+  /* init reference time for manifest file updates */
+  if (!GST_CLOCK_TIME_IS_VALID (demux->last_manifest_update))
+    demux->last_manifest_update = now;
+
+  /* update the manifest file */
+  if (now >= demux->last_manifest_update + update_period * GST_MSECOND) {
+    GST_DEBUG_OBJECT (demux, "Updating manifest file from URL %s",
+        demux->client->mpd_uri);
+    download =
+        gst_uri_downloader_fetch_uri (demux->downloader,
+        demux->client->mpd_uri);
+    if (download == NULL) {
+      GST_WARNING_OBJECT (demux,
+          "Failed to update the manifest file from URL %s",
+          demux->client->mpd_uri);
+    } else {
+      GstMpdClient *new_client = NULL;
+      guint period_idx;
+      const gchar *period_id;
+      GSList *iter;
+
+      buffer = gst_fragment_get_buffer(download);
+      g_object_unref (download);
+      /* parse the manifest file */
+      if (buffer == NULL) {
+        GST_WARNING_OBJECT (demux, "Error validating the manifest.");
+        return TRUE;
+      }
+
+      new_client = gst_mpd_client_new ();
+      new_client->mpd_uri = g_strdup (demux->client->mpd_uri);
+      if (!gst_mpd_parse (new_client,
+              (gchar *) GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer))) {
+        /* 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 manifest */
+        GST_WARNING_OBJECT (demux, "Error parsing the manifest.");
+        gst_buffer_unref (buffer);
+        return TRUE;
+      }
+
+      gst_buffer_unref (buffer);
+      GST_DEBUG_OBJECT (demux, "Updating manifest");
+
+      period_id = gst_mpd_client_get_period_id (demux->client);
+      period_idx = gst_mpd_client_get_period_index (demux->client);
+
+      /* setup video, audio and subtitle streams, starting from current Period */
+      if (!gst_mpd_client_setup_media_presentation (new_client)) {
+        /* TODO */
+      }
+
+      if (period_idx) {
+        /*If more than one period exists.*/
+        if (!gst_mpd_client_set_period_id (new_client, period_id)) {
+          GST_DEBUG_OBJECT (demux,
+              "Error setting up the updated manifest file");
+          return FALSE;
+        }
+      } else {
+        if (!gst_mpd_client_set_period_index (new_client, period_idx)) {
+          GST_DEBUG_OBJECT (demux,
+              "Error setting up the updated manifest file");
+          return FALSE;
+        }
+      }
+
+      if (!gst_dash_demux_setup_mpdparser_streams (demux, new_client)) {
+            GST_ERROR_OBJECT (demux, "Failed to setup streams on manifest "
+                "update");
+            return FALSE;
+      }
+
+      /* update the streams to play from the next segment */
+      for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
+        GstDashDemuxStream *demux_stream = iter->data;
+        GstActiveStream *new_stream;
+        GstClockTime ts;
+
+        new_stream = gst_mpdparser_get_active_stream_by_index (new_client,
+            demux_stream->idx);
+
+        if (!new_stream) {
+          GST_DEBUG_OBJECT (demux,
+              "Stream of index %d is missing from manifest update",
+              demux_stream->idx);
+          return FALSE;
+        }
+
+        if (gst_mpd_client_get_next_fragment_timestamp (demux->client,
+                demux_stream->idx, &ts)) {
+          gst_mpd_client_stream_seek (new_client, demux_stream->idx, ts);
+
+        } else
+            if (gst_mpd_client_get_last_fragment_timestamp (demux->client,
+                demux_stream->idx, &ts)) {
+          /* try to set to the old timestamp + 1 */
+          gst_mpd_client_stream_seek (new_client, demux_stream->idx, ts+1);
+        }
+      }
+
+      /*Remember download failed count*/
+      new_client->download_failed_count = demux->client->download_failed_count;
+
+      gst_mpd_client_free (demux->client);
+      demux->client = new_client;
+
+      /* Send an updated duration message */
+      duration =
+          gst_mpd_client_get_media_presentation_duration (demux->client);
+
+      if (duration != GST_CLOCK_TIME_NONE) {
+        GST_DEBUG_OBJECT (demux,
+            "Sending duration message : %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (duration));
+        gst_element_post_message (GST_ELEMENT (demux),
+            gst_message_new_duration(GST_OBJECT (demux), GST_FORMAT_TIME, duration));
+      } else {
+        GST_DEBUG_OBJECT (demux,
+            "mediaPresentationDuration unknown, can not send the duration message");
+      }
+      demux->last_manifest_update = gst_util_get_timestamp ();
+      GST_DEBUG_OBJECT (demux, "Manifest file successfully updated");
+    }
+  }
+  return TRUE;
+}
+
+static void
+gst_dash_demux_download_wait (GstDashDemux * demux, GstClockTime time_diff)
+{
+  gint64 end_time = g_get_monotonic_time () + time_diff / GST_USECOND;
+
+  GST_DEBUG_OBJECT (demux, "Download waiting for %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (time_diff));
+  g_cond_wait_until (&demux->download_cond, &demux->download_mutex, end_time);
+  GST_DEBUG_OBJECT (demux, "Download finished waiting");
+}
+
+static void
+gst_dash_demux_check_live(GstDashDemux* demux, GstActiveStream *fragment_stream,
+     GstClockTime fragment_ts)
+{
+  gint64 time_diff;
+  gint pos;
+
+  pos =
+      gst_mpd_client_check_time_position (demux->client, fragment_stream,
+      fragment_ts, &time_diff);
+  GST_DEBUG_OBJECT (demux,
+      "Checked position for fragment ts %" GST_TIME_FORMAT
+      ", res: %d, diff: %" G_GINT64_FORMAT, GST_TIME_ARGS (fragment_ts),
+      pos, time_diff);
+
+  time_diff *= GST_USECOND;
+  if (pos < 0) {
+    /* we're behind, try moving to the 'present' */
+    GDateTime *now = g_date_time_new_now_utc ();
+
+    GST_DEBUG_OBJECT (demux,
+        "Falling behind live stream, moving forward");
+      gst_mpd_client_seek_to_time(demux->client, now);
+    g_date_time_unref (now);
+
+  } else if (pos > 0) {
+    /* we're ahead, wait a little */
+
+    GST_DEBUG_OBJECT (demux, "Waiting for next segment to be created");
+    gst_dash_demux_download_wait (demux, time_diff);
+  } else {
+    demux->client->download_failed_count++;
+  }
+}
+
+/* gst_dash_demux_download_loop:
+ *
+ * Loop for the "download' task that fetches fragments based on the
+ * selected representations.
+ *
+ * Startup:
+ *
+ * The task is started from the stream loop.
+ *
+ * During playback:
+ *
+ * It sequentially fetches fragments corresponding to the current
+ * representations and pushes them into a queue.
+ *
+ * It tries to maintain the number of queued items within a predefined
+ * range: if the queue is full, it will pause, checking every 100 ms if
+ * it needs to restart downloading fragments.
+ *
+ * When a new set of fragments has been downloaded, it evaluates the
+ * download time to check if we can or should switch to a different
+ * set of representations.
+ *
+ * Teardown:
+ *
+ * The task will exit when it encounters an error or when the end of the
+ * manifest has been reached.
+ *
+ */
+void
+gst_dash_demux_download_loop (GstDashDemux * demux)
+{
+  GstActiveStream *fragment_stream = NULL;
+  GstClockTime fragment_ts;
+  if ( gst_mpd_client_is_live (demux->client) && demux->client->mpd_uri != NULL ) {
+    if (!gst_dash_demux_update_manifest(demux))
+      goto end_of_manifest;
+  }
+
+  /* try to switch to another set of representations if needed */
+  gst_dash_demux_select_representations (demux);
+
+  /* fetch the next fragment */
+  while (!gst_dash_demux_get_next_fragment (demux, &fragment_stream, &fragment_ts)) {
+    if (demux->end_of_period) {
+      GST_INFO_OBJECT (demux, "Reached the end of the Period");
+      /* setup video, audio and subtitle streams, starting from the next Period */
+      if (!gst_mpd_client_set_period_index (demux->client,
+              gst_mpd_client_get_period_index (demux->client) + 1)
+          || !gst_dash_demux_setup_all_streams (demux)) {
+        GST_INFO_OBJECT (demux, "Reached the end of the manifest file");
+        gst_task_start (demux->stream_task);
+        goto end_of_manifest;
+      }
+      /* start playing from the first segment of the new period */
+      gst_mpd_client_set_segment_index_for_all_streams (demux->client, 0);
+      demux->end_of_period = FALSE;
+    } else if (!demux->cancelled) {
+      gst_uri_downloader_reset (demux->downloader);
+      if(gst_mpd_client_is_live (demux->client)) {
+        gst_dash_demux_check_live (demux, fragment_stream, fragment_ts);
+      } else {
+        demux->client->download_failed_count++;
+      }
+
+      if (demux->client->download_failed_count < DEFAULT_FAILED_COUNT) {
+        GST_WARNING_OBJECT (demux, "Could not fetch the next fragment");
+        goto quit;
+      } else if (gst_mpd_client_set_next_baseURL_for_stream (demux->client)) {
+       GST_INFO_OBJECT (demux, "Current baseURL is %s. Trying to select another",
+                        gst_mpdparser_get_baseURL (demux->client));
+       demux->client->download_failed_count = 0;
+      } else {
+        goto error_downloading;
+      }
+    } else {
+      goto quit;
+    }
+  }
+  GST_INFO_OBJECT (demux, "Internal buffering : %" PRIu64 " s",
+      gst_dash_demux_get_buffering_time (demux) / GST_SECOND);
+  demux->client->download_failed_count = 0;
+
+
+quit:
+  {
+    return;
+  }
+
+end_of_manifest:
+  {
+    GST_INFO_OBJECT (demux, "Stopped download task");
+    gst_task_stop (demux->download_task);
+    return;
+  }
+
+error_downloading:
+  {
+    GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
+        ("Could not fetch the next fragment"), (NULL));
+    gst_dash_demux_stop (demux);
+    return;
+  }
+}
+
+static void
+gst_dash_demux_resume_stream_task (GstDashDemux * demux)
+{
+  gst_task_start (demux->stream_task);
+}
+
+static void
+gst_dash_demux_resume_download_task (GstDashDemux * demux)
+{
+  gst_uri_downloader_reset(demux->downloader);
+  gst_task_start (demux->download_task);
+}
+
+/* gst_dash_demux_select_representations:
+ *
+ * Select the most appropriate media representations based on a target
+ * bitrate.
+ *
+ * FIXME: all representations are selected against the same bitrate, but
+ * they will share the same bandwidth. This only works today because the
+ * audio representations bitrate usage is negligible as compared to the
+ * video representation one.
+ *
+ * Returns TRUE if a new set of representations has been selected
+ */
+static gboolean
+gst_dash_demux_select_representations (GstDashDemux * demux)
+{
+  GstDashDemuxStream *stream = NULL;
+  GstActiveStream *active_stream = NULL;
+  GList *rep_list = NULL;
+  GSList *iter;
+  gint new_index;
+  gboolean ret = FALSE;
+
+  GST_MPD_CLIENT_LOCK (demux->client);
+  for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
+    guint64 bitrate;
+
+    stream = iter->data;
+    active_stream =
+      gst_mpdparser_get_active_stream_by_index (demux->client, stream->idx);
+    if (!active_stream)
+      return FALSE;
+
+    /* retrieve representation list */
+    if (active_stream->cur_adapt_set)
+      rep_list = active_stream->cur_adapt_set->Representations;
+    if (!rep_list)
+      return FALSE;
+
+    bitrate = gst_download_rate_get_current_rate (&stream->dnl_rate) *
+      demux->bandwidth_usage;
+
+    GST_DEBUG_OBJECT (demux, "Trying to change bitrate to %" G_GUINT64_FORMAT, bitrate);
+
+    /* get representation index with current max_bandwidth */
+    new_index =
+        gst_mpdparser_get_rep_idx_with_max_bandwidth (rep_list, bitrate);
+
+    /* if no representation has the required bandwidth, take the lowest one */
+    if (new_index == -1)
+      new_index = 0;
+
+    if (new_index != active_stream->representation_idx) {
+      GstRepresentationNode *rep = g_list_nth_data (rep_list, new_index);
+      GST_INFO_OBJECT (demux, "Changing representation idx: %d %d %u",
+                      stream->idx, new_index, rep->bandwidth);
+      if (gst_mpd_client_setup_representation (demux->client, active_stream,
+                                              rep)) {
+       ret = TRUE;
+       stream->need_header = TRUE;
+        GST_INFO_OBJECT (demux, "Switching bitrate to %d",
+            active_stream->cur_representation->bandwidth);
+      } else {
+        GST_WARNING_OBJECT (demux,
+            "Can not switch representation, aborting...");
+      }
+    }
+  }
+  GST_MPD_CLIENT_UNLOCK (demux->client);
+  return ret;
+}
+
+static GstFragment *
+gst_dash_demux_get_next_header (GstDashDemux * demux, guint stream_idx)
+{
+  const gchar *initializationURL;
+  gchar *next_header_uri;
+  GstFragment *fragment;
+
+  if (!gst_mpd_client_get_next_header (demux->client, &initializationURL,
+          stream_idx))
+    return NULL;
+
+  if (strncmp (initializationURL, "http://", 7) != 0) {
+    next_header_uri =
+        g_strconcat (gst_mpdparser_get_baseURL (demux->client),
+        initializationURL, NULL);
+  } else {
+    next_header_uri = g_strdup (initializationURL);
+  }
+
+  GST_INFO_OBJECT (demux, "Fetching header %s", next_header_uri);
+
+  fragment = gst_uri_downloader_fetch_uri (demux->downloader, next_header_uri);
+  g_free (next_header_uri);
+  g_free (initializationURL);
+
+  return fragment;
+}
+
+static GstCaps *
+gst_dash_demux_get_video_input_caps (GstDashDemux * demux,
+    GstActiveStream * stream)
+{
+  guint width = 0, height = 0, bandwidth = 0;
+  const gchar *mimeType = NULL;
+  GstCaps *caps = NULL;
+
+  if (stream == NULL)
+    return NULL;
+#ifdef DASHDEMUX_MODIFICATION
+  /* caps need to inlcude resolution and bandwidth */
+    width = gst_mpd_client_get_video_stream_width (stream);
+    height = gst_mpd_client_get_video_stream_height (stream);
+    bandwidth = gst_mpd_client_get_video_stream_bandwidth (stream);
+#else
+  /* if bitstreamSwitching is true we dont need to swich pads on resolution change */
+  if (!gst_mpd_client_get_bitstream_switching_flag (stream)) {
+    width = gst_mpd_client_get_video_stream_width (stream);
+    height = gst_mpd_client_get_video_stream_height (stream);
+  }
+#endif
+  mimeType = gst_mpd_client_get_stream_mimeType (stream);
+  if (mimeType == NULL)
+    return NULL;
+
+  caps = gst_caps_new_simple (mimeType, NULL);
+  if (width > 0 && height > 0) {
+    gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height",
+        G_TYPE_INT, height, NULL);
+  }
+
+  if (bandwidth > 0)
+    gst_caps_set_simple (caps, "bandwidth", G_TYPE_INT, bandwidth, NULL);
+
+  gst_caps_set_simple (caps, "max-width", G_TYPE_INT, demux->max_video_width, "max-height",
+      G_TYPE_INT, demux->max_video_height, NULL);
+
+/*  add ContentProtection to caps  */
+  if ( stream->cur_adapt_set->RepresentationBase->ContentProtection != NULL){
+    GList *list;
+    GstDescriptorType *ContentProtectionDesc;
+
+    list = g_list_first (stream->cur_adapt_set->RepresentationBase->ContentProtection);
+    ContentProtectionDesc = (GstDescriptorType *) list->data;
+    gchar *schemeIdUri = ContentProtectionDesc->schemeIdUri;
+    gchar *msprPro = ContentProtectionDesc->msprPro;
+
+  if ( (schemeIdUri != NULL) && (msprPro != NULL) ){
+    gst_caps_set_simple (caps, "contentprotection_scheme_iduri", G_TYPE_STRING, schemeIdUri, "mspr:pro", G_TYPE_STRING, msprPro, NULL);
+  }
+ }
+  return caps;
+}
+
+static GstCaps *
+gst_dash_demux_get_audio_input_caps (GstDashDemux * demux,
+    GstActiveStream * stream)
+{
+  guint rate = 0, channels = 0;
+  const gchar *mimeType;
+  GstCaps *caps = NULL;
+
+  if (stream == NULL)
+    return NULL;
+
+  /* if bitstreamSwitching is true we dont need to swich pads on rate/channels change */
+  if (!gst_mpd_client_get_bitstream_switching_flag (stream)) {
+    channels = gst_mpd_client_get_audio_stream_num_channels (stream);
+    rate = gst_mpd_client_get_audio_stream_rate (stream);
+  }
+  mimeType = gst_mpd_client_get_stream_mimeType (stream);
+  if (mimeType == NULL)
+    return NULL;
+
+  caps = gst_caps_new_simple (mimeType, NULL);
+  if (rate > 0) {
+    gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate, NULL);
+  }
+  if (channels > 0) {
+    gst_caps_set_simple (caps, "channels", G_TYPE_INT, channels, NULL);
+  }
+
+/*  add ContentProtection to caps  */
+  if ( stream->cur_adapt_set->RepresentationBase->ContentProtection != NULL){
+    GList *list;
+    GstDescriptorType *ContentProtectionDesc;
+
+    list = g_list_first (stream->cur_adapt_set->RepresentationBase->ContentProtection);
+    ContentProtectionDesc = (GstDescriptorType *) list->data;
+    gchar *schemeIdUri = ContentProtectionDesc->schemeIdUri;
+    gchar *msprPro = ContentProtectionDesc->msprPro;
+
+  if ( (schemeIdUri != NULL) && (msprPro != NULL) ){
+    gst_caps_set_simple (caps, "contentprotection_scheme_iduri", G_TYPE_STRING, schemeIdUri, "mspr:pro", G_TYPE_STRING, msprPro, NULL);
+  }
+ }
+  return caps;
+}
+
+static GstCaps *
+gst_dash_demux_get_application_input_caps (GstDashDemux * demux,
+    GstActiveStream * stream)
+{
+  const gchar *mimeType;
+  GstCaps *caps = NULL;
+
+  if (stream == NULL)
+    return NULL;
+
+  mimeType = gst_mpd_client_get_stream_mimeType (stream);
+  if (mimeType == NULL)
+    return NULL;
+
+  caps = gst_caps_new_simple (mimeType, NULL);
+
+  return caps;
+}
+
+static GstCaps *
+gst_dash_demux_get_input_caps (GstDashDemux * demux, GstActiveStream * stream)
+{
+  GstCaps *caps;
+  switch (stream->mimeType) {
+    case GST_STREAM_VIDEO:
+      caps = gst_dash_demux_get_video_input_caps (demux, stream);
+      break;
+    case GST_STREAM_AUDIO:
+      caps = gst_dash_demux_get_audio_input_caps (demux, stream);
+      break;
+    case GST_STREAM_APPLICATION:
+      caps = gst_dash_demux_get_application_input_caps (demux, stream);
+      break;
+    default:
+      return GST_CAPS_NONE;
+  }
+  /*Need to signal downstream elements about dash*/
+  gst_caps_set_simple(caps, "variant", G_TYPE_STRING, "dash-fragmented", NULL);
+  return caps;
+}
+
+/* gst_dash_demux_get_next_fragment_set:
+ *
+ * Get the next set of fragments for the current representations.
+ *
+ * This function uses the generic URI downloader API.
+ *
+ * Returns FALSE if an error occured while downloading fragments
+ *
+ */
+static gboolean
+gst_dash_demux_get_next_fragment (GstDashDemux * demux,GstActiveStream **fragment_stream,
+     GstClockTime *selected_ts)
+{
+  GstActiveStream *stream;
+  GstDashDemuxStream *dash_stream;
+  GstDashDemuxStream *selected_stream = NULL;
+  GstFragment *download, *header;
+  gchar *next_fragment_uri;
+  GstClockTime duration;
+  GstClockTime timestamp;
+  GstClockTime min_timestamp = GST_CLOCK_TIME_NONE;
+  gboolean discont;
+  GTimeVal now;
+  GTimeVal start;
+  GstClockTime diff;
+  guint64 size_buffer = 0;
+  GstBuffer *buffer;
+  guint stream_idx;
+  gboolean end_of_period = TRUE;
+
+  /*Select stream with smallest progress*/
+  for (stream_idx = 0; stream_idx < g_slist_length (demux->streams); stream_idx++) {
+    dash_stream = g_slist_nth_data (demux->streams, stream_idx);
+
+    if (dash_stream->download_end_of_period)
+      continue;
+
+    if (gst_mpd_client_get_next_fragment_timestamp (demux->client, stream_idx, &timestamp)) {
+      if( timestamp < min_timestamp || !GST_CLOCK_TIME_IS_VALID(min_timestamp) ) {
+        selected_stream = dash_stream;
+        min_timestamp = timestamp;
+      }
+    } else {
+      GstEvent *event = NULL;
+
+      GST_INFO_OBJECT (demux,
+          "This Period doesn't contain more fragments for stream %u",
+          dash_stream->idx);
+
+      /* check if this is live and we should wait for more data */
+      if (gst_mpd_client_is_live (demux->client)
+          && demux->client->mpd_node->minimumUpdatePeriod != -1) {
+        end_of_period = FALSE;
+        continue;
+      }
+
+      if (gst_mpd_client_has_next_period (demux->client)) {
+        event = gst_event_new_dash_eop ();
+      } else {
+        GST_DEBUG_OBJECT (demux,
+            "No more fragments or periods for this stream, setting EOS");
+        event = gst_event_new_eos ();
+      }
+      dash_stream->download_end_of_period = TRUE;
+      gst_dash_demux_stream_push_event (dash_stream, event);
+    }
+  }
+
+  if (selected_ts)
+    *selected_ts = min_timestamp;
+  if (fragment_stream && selected_stream)
+    *fragment_stream = gst_mpdparser_get_active_stream_by_index (demux->client, selected_stream->idx);
+   /* Fetch next fragment from selected stream */
+  if(selected_stream) {
+
+    if (!gst_mpd_client_get_next_fragment (demux->client,
+            selected_stream->idx, &discont, &next_fragment_uri, &duration, &timestamp)) {
+      GST_WARNING_OBJECT (demux, "Failed to download fragment for stream %d", selected_stream->idx);
+    } else {
+
+      g_get_current_time (&start);
+      GST_INFO_OBJECT (demux, "Fetching next fragment stream=%d ts=%"GST_TIME_FORMAT" url=%s",
+                       selected_stream->idx, GST_TIME_ARGS(timestamp), next_fragment_uri);
+
+      stream = gst_mpdparser_get_active_stream_by_index (demux->client, selected_stream->idx);
+
+      end_of_period = FALSE;
+
+      download = gst_uri_downloader_fetch_uri (demux->downloader,
+          next_fragment_uri);
+      g_free (next_fragment_uri);
+
+      if (stream == NULL)
+        return FALSE;
+
+      if (download == NULL) {
+        guint segment_idx = gst_mpd_client_get_segment_index ( stream );
+        if(segment_idx > 0) {
+          /*Move to previous segment if download failed*/
+          gst_mpd_client_set_segment_index (stream, segment_idx - 1);
+        }
+        return FALSE;
+      }
+
+      download->start_time = timestamp;
+      download->stop_time = timestamp + duration;
+
+      download->index = gst_mpd_client_get_segment_index (stream) - 1;
+
+      GstCaps *caps = gst_dash_demux_get_input_caps (demux, stream);
+      buffer = gst_fragment_get_buffer (download);
+      g_return_val_if_fail (buffer != NULL, FALSE);
+
+      if (selected_stream->need_header) {
+        /* Store the new input caps for that stream */
+        gst_caps_replace (&dash_stream->input_caps, caps);
+        GST_INFO_OBJECT (demux, "Input source caps: %" GST_PTR_FORMAT,
+            dash_stream->input_caps);
+
+        /* We need to fetch a new header */
+        if ((header = gst_dash_demux_get_next_header (demux, selected_stream->idx)) == NULL) {
+          GST_INFO_OBJECT (demux, "Unable to fetch header");
+        } else {
+          /* Replace fragment buffer with a new one including the header */
+          GstBuffer *header_buffer = gst_fragment_get_buffer(header);
+          buffer = gst_buffer_join(header_buffer, buffer);
+          g_object_unref (header);
+         selected_stream->need_header = FALSE;
+        }
+      } else {
+        gst_caps_unref (caps);
+      }
+
+      g_get_current_time (&now);
+      g_object_unref (download);
+
+      gst_buffer_set_caps(buffer, dash_stream->input_caps);
+      GST_BUFFER_TIMESTAMP(buffer) = timestamp;
+      GST_BUFFER_DURATION(buffer) = duration;
+      GST_BUFFER_OFFSET(buffer) = gst_mpd_client_get_segment_index (stream) - 1;
+      size_buffer = GST_BUFFER_SIZE (buffer);
+      /* Push fragment into the queue */
+      gst_dash_demux_stream_push_data (selected_stream, buffer);
+      diff = (GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (start));
+      gst_download_rate_add_rate (&selected_stream->dnl_rate, size_buffer, diff, duration);
+      GST_DEBUG_OBJECT (demux,
+                        "Stream: %d Download rate = %" G_GUINT64_FORMAT " Kbits/s (%" G_GUINT64_FORMAT
+                        " Ko in %.2f s)\n", selected_stream->idx,
+                        gst_download_rate_get_current_rate (&selected_stream->dnl_rate) / 1000,
+                        size_buffer / 1024,
+                        ((double) diff / GST_SECOND));
+    }
+  }
+
+  demux->end_of_period = end_of_period;
+
+  return !end_of_period;
+}
diff --git a/dashdemux/src/gstdashdemux.h b/dashdemux/src/gstdashdemux.h
new file mode 100755 (executable)
index 0000000..9e3fe6c
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * DASH demux plugin for GStreamer
+ *
+ * gstdashdemux.h
+ *
+ * Copyright (C) 2012 Orange
+ *
+ * Authors:
+ *   David Corvoysier <david.corvoysier@orange.com>
+ *   Hamid Zakari <hamid.zakari@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_DASH_DEMUX_H__
+#define __GST_DASH_DEMUX_H__
+#define DASHDEMUX_MODIFICATION
+#include <gst/gst.h>
+#include <gst/base/gstdataqueue.h>
+#include "gstmpdparser.h"
+#include "gstfragmented.h"
+#include "gsturidownloader.h"
+#include "gstdownloadrate.h"
+
+G_BEGIN_DECLS
+#define GST_TYPE_DASH_DEMUX \
+        (gst_dash_demux_get_type())
+#define GST_DASH_DEMUX(obj) \
+        (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DASH_DEMUX,GstDashDemux))
+#define GST_DASH_DEMUX_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DASH_DEMUX,GstDashDemuxClass))
+#define GST_IS_DASH_DEMUX(obj) \
+        (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DASH_DEMUX))
+#define GST_IS_DASH_DEMUX_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DASH_DEMUX))
+//
+typedef struct _GstDashDemux GstDashDemux;
+typedef struct _GstDashDemuxClass GstDashDemuxClass;
+typedef struct _GstDashDemuxStream GstDashDemuxStream;
+
+struct _GstDashDemuxStream {
+  guint idx;
+  GstPad *srcpad;
+  GstCaps *output_caps;
+  GstCaps *input_caps;
+  GstDataQueue *queue;
+  GstClockTime start_time;
+  gboolean download_end_of_period;
+  gboolean stream_end_of_period;
+  gboolean stream_eos;
+  gboolean need_header;
+  gboolean need_segment;
+  GstDownloadRate dnl_rate;
+};
+
+#define MAX_LANGUAGES 20
+/**
+ * GstDashDemux:
+ *
+ * Opaque #GstDashDemux data structure.
+ */
+struct _GstDashDemux
+{
+  GstElement parent;
+  GstPad *sinkpad;
+  GSList *streams;
+  gint max_video_width;
+  gint max_video_height;
+
+  GstBuffer *manifest;
+  GstUriDownloader *downloader;
+  GstMpdClient *client;         /* MPD client */
+  gboolean end_of_period;
+  gboolean end_of_manifest;
+
+  /* Properties */
+  GstClockTime max_buffering_time;      /* Maximum buffering time accumulated during playback */
+  gfloat bandwidth_usage;       /* Percentage of the available bandwidth to use       */
+  guint64 max_bitrate;          /* max of bitrate supported by target decoder         */
+
+  /* Streaming task */
+  GstTask *stream_task;
+  GStaticRecMutex stream_lock;
+  GMutex *stream_timed_lock;
+
+  /* Download task */
+  GstTask *download_task;
+  GStaticRecMutex download_lock;
+  volatile gboolean cancelled;
+  GMutex download_mutex;
+  GCond download_cond;
+
+  /* Manifest update */
+  GstClockTime last_manifest_update;
+};
+
+struct _GstDashDemuxClass
+{
+  GstElementClass parent_class;
+};
+
+GType gst_dash_demux_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_DASH_DEMUX_H__ */
diff --git a/dashdemux/src/gstdownloadrate.c b/dashdemux/src/gstdownloadrate.c
new file mode 100644 (file)
index 0000000..9913e0a
--- /dev/null
@@ -0,0 +1,137 @@
+/* GStreamer
+ * Copyright (C) 2011 Andoni Morales Alastruey <ylatuya@gmail.com>
+ * Copyright (C) 2012 Smart TV Alliance
+ *  Author: Louis-Francis Ratté-Boulianne <lfrb@collabora.com>, Collabora Ltd.
+ *
+ * gstfragment.c:
+ *
+ * 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 <glib.h>
+#include "gstdownloadrate.h"
+
+static void
+_gst_download_rate_check_remove_rates (GstDownloadRate * rate)
+{
+  if (rate->max_length == 0)
+    return;
+
+  while (g_queue_get_length (&rate->queue) > rate->max_length) {
+    guint bitrate = GPOINTER_TO_UINT (g_queue_pop_head (&rate->queue));
+
+    rate->total -= bitrate;
+  }
+}
+
+void
+gst_download_rate_init (GstDownloadRate * rate)
+{
+  g_queue_init (&rate->queue);
+  g_mutex_init (&rate->mutex);
+  rate->total = 0;
+  rate->max_length = 0;
+  rate->aver_period = 0;
+}
+
+void
+gst_download_rate_deinit (GstDownloadRate * rate)
+{
+  gst_download_rate_clear (rate);
+  g_mutex_clear (&rate->mutex);
+}
+
+void
+gst_download_rate_set_max_length (GstDownloadRate * rate, gint max_length)
+{
+  g_mutex_lock (&rate->mutex);
+  rate->max_length = max_length;
+  _gst_download_rate_check_remove_rates (rate);
+  g_mutex_unlock (&rate->mutex);
+}
+
+gint
+gst_download_rate_get_max_length (GstDownloadRate * rate)
+{
+  guint ret;
+  g_mutex_lock (&rate->mutex);
+  ret = rate->max_length;
+  g_mutex_unlock (&rate->mutex);
+
+  return ret;
+}
+
+void
+  gst_download_rate_set_aver_period (GstDownloadRate * rate, guint64 aver_period)
+{
+  g_mutex_lock (&rate->mutex);
+  rate->aver_period = aver_period;
+  _gst_download_rate_check_remove_rates (rate);
+  g_mutex_unlock (&rate->mutex);
+}
+
+GstClockTime
+gst_download_rate_get_aver_period (GstDownloadRate * rate)
+{
+  guint64 ret;
+  g_mutex_lock (&rate->mutex);
+  ret = rate->aver_period;
+  g_mutex_unlock (&rate->mutex);
+
+  return ret;
+}
+
+void
+gst_download_rate_clear (GstDownloadRate * rate)
+{
+  g_mutex_lock (&rate->mutex);
+  g_queue_clear (&rate->queue);
+  rate->total = 0;
+  g_mutex_unlock (&rate->mutex);
+}
+
+void
+gst_download_rate_add_rate (GstDownloadRate * rate, guint bytes, guint64 time, GstClockTime duration)
+{
+  guint64 bitrate;
+  g_mutex_lock (&rate->mutex);
+
+  /* convert from bytes / nanoseconds to bits per second */
+  bitrate = G_GUINT64_CONSTANT (8000000000) * bytes / ((double) time);
+  g_queue_push_tail (&rate->queue, GUINT_TO_POINTER ((guint) bitrate));
+  rate->total += bitrate;
+
+  if ( duration * rate->max_length > rate->aver_period )
+    rate->max_length = 
+      duration < rate->aver_period ? rate->aver_period / duration : 1;
+
+  _gst_download_rate_check_remove_rates (rate);
+  g_mutex_unlock (&rate->mutex);
+}
+
+guint64
+gst_download_rate_get_current_rate (GstDownloadRate * rate)
+{
+  guint64 ret;
+  g_mutex_lock (&rate->mutex);
+  if (g_queue_get_length (&rate->queue)) 
+    ret = rate->total / g_queue_get_length (&rate->queue);
+  else
+    ret = 0;
+  g_mutex_unlock (&rate->mutex);
+
+  return ret;
+}
diff --git a/dashdemux/src/gstdownloadrate.h b/dashdemux/src/gstdownloadrate.h
new file mode 100644 (file)
index 0000000..e4da338
--- /dev/null
@@ -0,0 +1,58 @@
+/* GStreamer
+ * Copyright (C) 2012 Smart TV Alliance
+ *  Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>, Collabora Ltd.
+ *
+ * gstdownloadrate.h:
+ *
+ * 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_DOWNLOAD_RATE_H__
+#define __GST_DOWNLOAD_RATE_H__
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstDownloadRate GstDownloadRate;
+
+struct _GstDownloadRate
+{
+  GQueue queue;
+  GMutex mutex;
+
+  gint max_length;
+  guint64 aver_period;
+  guint64 total;
+};
+
+void gst_download_rate_init (GstDownloadRate * rate);
+void gst_download_rate_deinit (GstDownloadRate * rate);
+
+void gst_download_rate_set_max_length (GstDownloadRate * rate, gint max_length);
+gint gst_download_rate_get_max_length (GstDownloadRate * rate);
+
+void gst_download_rate_set_aver_period (GstDownloadRate * rate, GstClockTime aver_period);
+GstClockTime gst_download_rate_get_aver_period (GstDownloadRate * rate);
+
+void gst_download_rate_clear (GstDownloadRate * rate);
+void gst_download_rate_add_rate (GstDownloadRate * rate, guint bytes, guint64 time, GstClockTime duration);
+
+guint64 gst_download_rate_get_current_rate (GstDownloadRate * rate);
+
+G_END_DECLS
+#endif /* __GST_DOWNLOAD_RATE_H__ */
diff --git a/dashdemux/src/gstfragment.c b/dashdemux/src/gstfragment.c
new file mode 100755 (executable)
index 0000000..2102726
--- /dev/null
@@ -0,0 +1,211 @@
+/* GStreamer
+ * Copyright (C) 2011 Andoni Morales Alastruey <ylatuya@gmail.com>
+ *
+ * gstfragment.c:
+ *
+ * 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 <glib.h>
+#include <gst/base/gsttypefindhelper.h>
+#include <gst/base/gstadapter.h>
+#include "glibcompat.h"
+#include "gstfragmented.h"
+#include "gstfragment.h"
+
+#define GST_CAT_DEFAULT fragmented_debug
+
+#define GST_FRAGMENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_FRAGMENT, GstFragmentPrivate))
+
+enum
+{
+  PROP_0,
+  PROP_INDEX,
+  PROP_NAME,
+  PROP_DURATION,
+  PROP_DISCONTINOUS,
+  PROP_BUFFER_LIST,
+  PROP_CAPS,
+  PROP_LAST
+};
+
+struct _GstFragmentPrivate
+{
+  GstBuffer *buffer;
+  GstAdapter *adapter;
+};
+
+G_DEFINE_TYPE (GstFragment, gst_fragment, G_TYPE_OBJECT);
+
+static void gst_fragment_dispose (GObject * object);
+static void gst_fragment_finalize (GObject * object);
+
+static void
+gst_fragment_get_property (GObject * object,
+    guint property_id, GValue * value, GParamSpec * pspec)
+{
+  GstFragment *fragment = GST_FRAGMENT (object);
+
+  switch (property_id) {
+    case PROP_INDEX:
+      g_value_set_uint (value, fragment->index);
+      break;
+
+    case PROP_NAME:
+      g_value_set_string (value, fragment->name);
+      break;
+
+    case PROP_DURATION:
+      g_value_set_uint64 (value, fragment->stop_time - fragment->start_time);
+      break;
+
+    case PROP_DISCONTINOUS:
+      g_value_set_boolean (value, fragment->discontinuous);
+      break;
+
+    default:
+      /* We don't have any other property... */
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+
+static void
+gst_fragment_class_init (GstFragmentClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (GstFragmentPrivate));
+
+  gobject_class->get_property = gst_fragment_get_property;
+  gobject_class->dispose = gst_fragment_dispose;
+  gobject_class->finalize = gst_fragment_finalize;
+
+  g_object_class_install_property (gobject_class, PROP_INDEX,
+      g_param_spec_uint ("index", "Index", "Index of the fragment", 0,
+          G_MAXUINT, 0, G_PARAM_READABLE));
+
+  g_object_class_install_property (gobject_class, PROP_NAME,
+      g_param_spec_string ("name", "Name",
+          "Name of the fragment (eg:fragment-12.ts)", NULL, G_PARAM_READABLE));
+
+  g_object_class_install_property (gobject_class, PROP_DISCONTINOUS,
+      g_param_spec_boolean ("discontinuous", "Discontinous",
+          "Whether this fragment has a discontinuity or not",
+          FALSE, G_PARAM_READABLE));
+
+  g_object_class_install_property (gobject_class, PROP_DURATION,
+      g_param_spec_uint64 ("duration", "Fragment duration",
+          "Duration of the fragment", 0, G_MAXUINT64, 0, G_PARAM_READABLE));
+
+}
+
+static void
+gst_fragment_init (GstFragment * fragment)
+{
+  GstFragmentPrivate *priv;
+
+  fragment->priv = priv = GST_FRAGMENT_GET_PRIVATE (fragment);
+
+  priv->adapter = gst_adapter_new ();
+  fragment->download_start_time = g_get_real_time ();
+  fragment->start_time = 0;
+  fragment->stop_time = 0;
+  fragment->index = 0;
+  fragment->name = g_strdup ("");
+  fragment->completed = FALSE;
+  fragment->discontinuous = FALSE;
+}
+
+GstFragment *
+gst_fragment_new (void)
+{
+  return GST_FRAGMENT (g_object_new (GST_TYPE_FRAGMENT, NULL));
+}
+
+static void
+gst_fragment_finalize (GObject * gobject)
+{
+  GstFragment *fragment = GST_FRAGMENT (gobject);
+
+  g_free (fragment->name);
+
+  G_OBJECT_CLASS (gst_fragment_parent_class)->finalize (gobject);
+}
+
+void
+gst_fragment_dispose (GObject * object)
+{
+  GstFragmentPrivate *priv = GST_FRAGMENT (object)->priv;
+
+  if (priv->buffer != NULL) {
+    gst_buffer_unref (priv->buffer);
+    priv->buffer = NULL;
+  }
+
+  if (priv->adapter != NULL) {
+    g_object_unref (priv->adapter);
+    priv->adapter = NULL;
+  }
+
+  G_OBJECT_CLASS (gst_fragment_parent_class)->dispose (object);
+}
+
+GstBuffer *
+gst_fragment_get_buffer (GstFragment * fragment)
+{
+  g_return_val_if_fail (fragment != NULL, NULL);
+
+  if (!fragment->completed)
+    return NULL;
+
+  if(!fragment->priv->buffer) {
+    fragment->priv->buffer = gst_adapter_take_buffer(fragment->priv->adapter,
+                              gst_adapter_available(fragment->priv->adapter));
+  }
+
+  return gst_buffer_ref(fragment->priv->buffer);
+}
+
+guint64
+gst_fragment_get_total_size (GstFragment * fragment)
+{
+  g_return_val_if_fail (fragment != NULL, 0);
+
+  if (fragment->priv->buffer)
+    return GST_BUFFER_SIZE(fragment->priv->buffer);
+
+  return gst_adapter_available(fragment->priv->adapter);
+}
+
+
+
+gboolean
+gst_fragment_add_buffer (GstFragment * fragment, GstBuffer * buffer)
+{
+  g_return_val_if_fail (fragment != NULL, FALSE);
+  g_return_val_if_fail (buffer != NULL, FALSE);
+
+  if (fragment->completed) {
+    GST_WARNING ("Fragment is completed, could not add more buffers");
+    return FALSE;
+  }
+
+  gst_adapter_push(fragment->priv->adapter, buffer);
+  return TRUE;
+}
diff --git a/dashdemux/src/gstfragment.h b/dashdemux/src/gstfragment.h
new file mode 100755 (executable)
index 0000000..3068943
--- /dev/null
@@ -0,0 +1,69 @@
+/* GStreamer
+ * Copyright (C) 2011 Andoni Morales Alastruey <ylatuya@gmail.com>
+ *
+ * gstfragment.h:
+ *
+ * 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 __GSTFRAGMENT_H__
+#define __GSTFRAGMENT_H__
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_FRAGMENT (gst_fragment_get_type())
+#define GST_FRAGMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FRAGMENT,GstFragment))
+#define GST_FRAGMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FRAGMENT,GstFragmentClass))
+#define GST_IS_FRAGMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FRAGMENT))
+#define GST_IS_FRAGMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FRAGMENT))
+
+typedef struct _GstFragment GstFragment;
+typedef struct _GstFragmentPrivate GstFragmentPrivate;
+typedef struct _GstFragmentClass GstFragmentClass;
+
+struct _GstFragment
+{
+  GObject parent;
+
+  gchar * name;                 /* Name of the fragment */
+  gboolean completed;           /* Whether the fragment is complete or not */
+  guint64 download_start_time;  /* Epoch time when the download started */
+  guint64 download_stop_time;   /* Epoch time when the download finished */
+  guint64 start_time;           /* Start time of the fragment */
+  guint64 stop_time;            /* Stop time of the fragment */
+  gboolean index;               /* Index of the fragment */
+  gboolean discontinuous;       /* Whether this fragment is discontinuous or not */
+
+  GstFragmentPrivate *priv;
+};
+
+struct _GstFragmentClass
+{
+  GObjectClass parent_class;
+};
+
+GType gst_fragment_get_type (void);
+
+guint64 gst_fragment_get_total_size (GstFragment * fragment);
+GstBuffer *gst_fragment_get_buffer(GstFragment *fragment);
+gboolean gst_fragment_add_buffer (GstFragment *fragment, GstBuffer *buffer);
+GstFragment * gst_fragment_new (void);
+
+G_END_DECLS
+#endif /* __GSTFRAGMENT_H__ */
diff --git a/dashdemux/src/gstfragmented.h b/dashdemux/src/gstfragmented.h
new file mode 100755 (executable)
index 0000000..0214a93
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __GST_FRAGMENTED_H__
+#define __GST_FRAGMENTED_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+GST_DEBUG_CATEGORY_EXTERN (fragmented_debug);
+
+#define LOG_CAPS(obj, caps) GST_DEBUG_OBJECT (obj, "%s: %" GST_PTR_FORMAT, #caps, caps)
+
+G_END_DECLS
+
+#endif /* __GST_FRAGMENTED_H__ */
+
diff --git a/dashdemux/src/gstmpdparser.c b/dashdemux/src/gstmpdparser.c
new file mode 100755 (executable)
index 0000000..95afab9
--- /dev/null
@@ -0,0 +1,3941 @@
+/*
+ * DASH MPD parsing library
+ *
+ * gstmpdparser.c
+ *
+ * Copyright (C) 2012 STMicroelectronics
+ *
+ * Authors:
+ *   Gianluca Gennari <gennarone@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <libxml/tree.h>
+#include "gstfragmented.h"
+#include "gstmpdparser.h"
+
+#define GST_CAT_DEFAULT fragmented_debug
+
+/* Property parsing */
+static gchar *gst_mpdparser_get_xml_prop_string (xmlNode * a_node,
+    const gchar * property);
+static gchar **gst_mpdparser_get_xml_prop_string_vector_type (xmlNode * a_node,
+    const gchar * property);
+static guint gst_mpdparser_get_xml_prop_unsigned_integer (xmlNode * a_node,
+    const gchar * property, guint default_val);
+static guint *gst_mpdparser_get_xml_prop_uint_vector_type (xmlNode * a_node,
+    const gchar * property, guint * size);
+static gdouble gst_mpdparser_get_xml_prop_double (xmlNode * a_node,
+    const gchar * property);
+static gboolean gst_mpdparser_get_xml_prop_boolean (xmlNode * a_node,
+    const gchar * property);
+static GstMPDFileType gst_mpdparser_get_xml_prop_type (xmlNode * a_node,
+    const gchar * property);
+static GstSAPType gst_mpdparser_get_xml_prop_SAP_type (xmlNode * a_node,
+    const gchar * property);
+static GstRange *gst_mpdparser_get_xml_prop_range (xmlNode * a_node,
+    const gchar * property);
+static GstRatio *gst_mpdparser_get_xml_prop_ratio (xmlNode * a_node,
+    const gchar * property);
+static GstFrameRate *gst_mpdparser_get_xml_prop_framerate (xmlNode * a_node,
+    const gchar * property);
+static GstConditionalUintType *gst_mpdparser_get_xml_prop_cond_uint (xmlNode *
+    a_node, const gchar * property);
+static GstDateTime *gst_mpdparser_get_xml_prop_dateTime (xmlNode * a_node,
+    const gchar * property);
+static gint64 gst_mpdparser_get_xml_prop_duration (xmlNode * a_node,
+    const gchar * property);
+static gchar *gst_mpdparser_get_xml_node_content (xmlNode * a_node);
+static gchar *gst_mpdparser_get_xml_node_namespace (xmlNode * a_node,
+    const gchar * prefix);
+
+/* XML node parsing */
+static void gst_mpdparser_parse_baseURL_node (GList ** list, xmlNode * a_node);
+static void gst_mpdparser_parse_descriptor_type_node (GList ** list,
+    xmlNode * a_node);
+static void gst_mpdparser_parse_content_component_node (GList ** list,
+    xmlNode * a_node);
+static void gst_mpdparser_parse_location_node (GList ** list, xmlNode * a_node);
+static void gst_mpdparser_parse_subrepresentation_node (GList ** list,
+    xmlNode * a_node);
+static void gst_mpdparser_parse_segment_url_node (GList ** list,
+    xmlNode * a_node);
+static void gst_mpdparser_parse_url_type_node (GstURLType ** pointer,
+    xmlNode * a_node);
+static void gst_mpdparser_parse_seg_base_type_ext (GstSegmentBaseType **
+    pointer, xmlNode * a_node);
+static void gst_mpdparser_parse_s_node (GList ** list, xmlNode * a_node);
+static void gst_mpdparser_parse_segment_timeline_node (GstSegmentTimelineNode **
+    pointer, xmlNode * a_node);
+static void gst_mpdparser_parse_mult_seg_base_type_ext (GstMultSegmentBaseType
+    ** pointer, xmlNode * a_node);
+static void gst_mpdparser_parse_segment_list_node (GstSegmentListNode **
+    pointer, xmlNode * a_node);
+static void
+gst_mpdparser_parse_representation_base_type (GstRepresentationBaseType **
+    pointer, xmlNode * a_node);
+static void gst_mpdparser_parse_representation_node (GList ** list,
+    xmlNode * a_node);
+static void gst_mpdparser_parse_adaptation_set_node (GList ** list,
+    xmlNode * a_node);
+static void gst_mpdparser_parse_subset_node (GList ** list, xmlNode * a_node);
+static void gst_mpdparser_parse_segment_template_node (GstSegmentTemplateNode **
+    pointer, xmlNode * a_node);
+static void gst_mpdparser_parse_period_node (GList ** list, xmlNode * a_node);
+static void gst_mpdparser_parse_program_info_node (GList ** list,
+    xmlNode * a_node);
+static void gst_mpdparser_parse_metrics_range_node (GList ** list,
+    xmlNode * a_node);
+static void gst_mpdparser_parse_metrics_node (GList ** list, xmlNode * a_node);
+static void gst_mpdparser_parse_root_node (GstMPDNode ** pointer,
+    xmlNode * a_node);
+
+/* Helper functions */
+static gint convert_to_millisecs (gint decimals, gint pos);
+static int strncmp_ext (const char *s1, const char *s2);
+static GstStreamPeriod *gst_mpdparser_get_stream_period (GstMpdClient * client);
+static gchar *gst_mpdparser_parse_baseURL (GstMpdClient * client);
+static gchar *gst_mpdparser_get_segmentURL_for_range (const gchar *url,
+    GstRange * range);
+static gchar *gst_mpdparser_get_mediaURL (GstMpdClient * client,
+    GstSegmentURLNode * segmentURL);
+static gchar *gst_mpdparser_get_initializationURL (GstURLType *
+    InitializationURL);
+static gchar *gst_mpdparser_build_URL_from_template (const gchar * url_template,
+    const gchar * id, guint number, guint bandwidth, guint time);
+static gboolean gst_mpd_client_add_media_segment (GstActiveStream * stream,
+    GstSegmentURLNode * url_node, guint number, guint start,
+    GstClockTime start_time, GstClockTime duration);
+static const gchar *gst_mpdparser_mimetype_to_caps (const gchar * mimeType);
+static GstClockTime gst_mpd_client_get_segment_duration (GstMpdClient * client, GstActiveStream * stream);
+
+/* Adaptation Set */
+static GstAdaptationSetNode
+    *gst_mpdparser_get_first_adapt_set_with_mimeType (GList * AdaptationSets,
+    const gchar * mimeType);
+static GstAdaptationSetNode
+    *gst_mpdparser_get_adapt_set_with_mimeType_and_idx (GList * AdaptationSets,
+    const gchar * mimeType, gint idx);
+static GstAdaptationSetNode
+    *gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang (GList *
+    AdaptationSets, const gchar * mimeType, const gchar * lang);
+
+/* Representation */
+static GstRepresentationNode *gst_mpdparser_get_lowest_representation (GList *
+    Representations);
+#if 0
+static GstRepresentationNode *gst_mpdparser_get_highest_representation (GList *
+    Representations);
+static GstRepresentationNode
+    *gst_mpdparser_get_representation_with_max_bandwidth (GList *
+    Representations, guint64 max_bandwidth);
+#endif
+static GstSegmentBaseType *gst_mpdparser_get_segment_base (GstPeriodNode *
+    Period, GstAdaptationSetNode * AdaptationSet,
+    GstRepresentationNode * Representation);
+static GstSegmentListNode *gst_mpdparser_get_segment_list (GstPeriodNode *
+    Period, GstAdaptationSetNode * AdaptationSet,
+    GstRepresentationNode * Representation);
+
+/* Memory management */
+static void gst_mpdparser_free_mpd_node (GstMPDNode * mpd_node);
+static void gst_mpdparser_free_prog_info_node (GstProgramInformationNode *
+    prog_info_node);
+static void gst_mpdparser_free_metrics_node (GstMetricsNode * metrics_node);
+static void gst_mpdparser_free_metrics_range_node (GstMetricsRangeNode *
+    metrics_range_node);
+static void gst_mpdparser_free_period_node (GstPeriodNode * period_node);
+static void gst_mpdparser_free_subset_node (GstSubsetNode * subset_node);
+static void gst_mpdparser_free_segment_template_node (GstSegmentTemplateNode *
+    segment_template_node);
+static void
+gst_mpdparser_free_representation_base_type (GstRepresentationBaseType *
+    representation_base);
+static void gst_mpdparser_free_adaptation_set_node (GstAdaptationSetNode *
+    adaptation_set_node);
+static void gst_mpdparser_free_representation_node (GstRepresentationNode *
+    representation_node);
+static void gst_mpdparser_free_subrepresentation_node (GstSubRepresentationNode
+    * subrep_node);
+static void gst_mpdparser_free_s_node (GstSNode * s_node);
+static void gst_mpdparser_free_segment_timeline_node (GstSegmentTimelineNode *
+    seg_timeline);
+static void gst_mpdparser_free_url_type_node (GstURLType * url_type_node);
+static void gst_mpdparser_free_seg_base_type_ext (GstSegmentBaseType *
+    seg_base_type);
+static void gst_mpdparser_free_mult_seg_base_type_ext (GstMultSegmentBaseType *
+    mult_seg_base_type);
+static void gst_mpdparser_free_segment_list_node (GstSegmentListNode *
+    segment_list_node);
+static void gst_mpdparser_free_segment_url_node (GstSegmentURLNode *
+    segment_url);
+static void gst_mpdparser_free_base_url_node (GstBaseURL * base_url_node);
+static void gst_mpdparser_free_descriptor_type_node (GstDescriptorType *
+    descriptor_type);
+static void gst_mpdparser_free_content_component_node (GstContentComponentNode *
+    content_component_node);
+static void gst_mpdparser_free_stream_period (GstStreamPeriod * stream_period);
+static void gst_mpdparser_free_media_segment (GstMediaSegment * media_segment);
+static void gst_mpdparser_free_active_stream (GstActiveStream * active_stream);
+
+/* functions to parse node namespaces, content and properties */
+static gchar *
+gst_mpdparser_get_xml_prop_string (xmlNode * a_node, const gchar * property)
+{
+  xmlChar *prop_string;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    GST_LOG (" - %s: %s", property, prop_string);
+  }
+
+  return (gchar *) prop_string;
+}
+
+static gchar **
+gst_mpdparser_get_xml_prop_string_vector_type (xmlNode * a_node,
+    const gchar * property)
+{
+  xmlChar *prop_string;
+  gchar **prop_string_vector = NULL;
+  guint i = 0;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    prop_string_vector = g_strsplit ((gchar *) prop_string, " ", -1);
+    if (!prop_string_vector) {
+      GST_WARNING ("Scan of string vector property failed!");
+      return NULL;
+    }
+    GST_LOG (" - %s:", property);
+    while (prop_string_vector[i]) {
+      GST_LOG ("    %s", prop_string_vector[i]);
+      i++;
+    }
+    xmlFree (prop_string);
+  }
+
+  return prop_string_vector;
+}
+
+static guint
+gst_mpdparser_get_xml_prop_unsigned_integer (xmlNode * a_node,
+    const gchar * property, guint default_val)
+{
+  xmlChar *prop_string;
+  guint prop_unsigned_integer = default_val;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    if (sscanf ((gchar *) prop_string, "%u", &prop_unsigned_integer)) {
+      GST_LOG (" - %s: %u", property, prop_unsigned_integer);
+    } else {
+      GST_WARNING
+          ("failed to parse unsigned integer property %s from xml string %s",
+          property, prop_string);
+    }
+    xmlFree (prop_string);
+  }
+
+  return prop_unsigned_integer;
+}
+
+static guint *
+gst_mpdparser_get_xml_prop_uint_vector_type (xmlNode * a_node,
+    const gchar * property, guint * size)
+{
+  xmlChar *prop_string;
+  gchar **str_vector;
+  guint *prop_uint_vector = NULL, i;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    str_vector = g_strsplit ((gchar *) prop_string, " ", -1);
+    if (!str_vector) {
+      GST_WARNING ("Scan of uint vector property failed!");
+      return NULL;
+    }
+    *size = g_strv_length (str_vector);
+    prop_uint_vector = g_malloc (*size * sizeof (guint));
+    if (!prop_uint_vector) {
+      GST_WARNING ("Array allocation failed!");
+    } else {
+      GST_LOG (" - %s:", property);
+      for (i = 0; i < *size; i++) {
+        if (sscanf ((gchar *) str_vector[i], "%u", &prop_uint_vector[i])) {
+          GST_LOG ("    %u", prop_uint_vector[i]);
+        } else {
+          GST_WARNING
+              ("failed to parse uint vector type property %s from xml string %s",
+              property, str_vector[i]);
+        }
+      }
+    }
+    xmlFree (prop_string);
+    g_strfreev (str_vector);
+  }
+
+  return prop_uint_vector;
+}
+
+static gdouble
+gst_mpdparser_get_xml_prop_double (xmlNode * a_node, const gchar * property)
+{
+  xmlChar *prop_string;
+  gdouble prop_double = 0;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    if (sscanf ((gchar *) prop_string, "%lf", &prop_double)) {
+      GST_LOG (" - %s: %lf", property, prop_double);
+    } else {
+      GST_WARNING ("failed to parse double property %s from xml string %s",
+          property, prop_string);
+    }
+    xmlFree (prop_string);
+  }
+
+  return prop_double;
+}
+
+static gboolean
+gst_mpdparser_get_xml_prop_boolean (xmlNode * a_node, const gchar * property)
+{
+  xmlChar *prop_string;
+  gboolean prop_bool = FALSE;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    if (xmlStrcmp (prop_string, (xmlChar *) "false") == 0) {
+      GST_LOG (" - %s: false", property);
+    } else if (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 GstMPDFileType
+gst_mpdparser_get_xml_prop_type (xmlNode * a_node, const gchar * property)
+{
+  xmlChar *prop_string;
+  GstMPDFileType prop_type = GST_MPD_FILE_TYPE_STATIC;  /* default */
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    if (xmlStrcmp (prop_string, (xmlChar *) "OnDemand") == 0
+        || xmlStrcmp (prop_string, (xmlChar *) "static") == 0) {
+      GST_LOG (" - %s: static", property);
+      prop_type = GST_MPD_FILE_TYPE_STATIC;
+    } else if (xmlStrcmp (prop_string, (xmlChar *) "Live") == 0
+        || xmlStrcmp (prop_string, (xmlChar *) "dynamic") == 0) {
+      GST_LOG (" - %s: dynamic", property);
+      prop_type = GST_MPD_FILE_TYPE_DYNAMIC;
+    } else {
+      GST_WARNING ("failed to parse MPD type property %s from xml string %s",
+          property, prop_string);
+    }
+    xmlFree (prop_string);
+  }
+
+  return prop_type;
+}
+
+static GstSAPType
+gst_mpdparser_get_xml_prop_SAP_type (xmlNode * a_node, const gchar * property)
+{
+  xmlChar *prop_string;
+  guint prop_SAP_type = 0;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    if (sscanf ((gchar *) prop_string, "%u", &prop_SAP_type)
+        && prop_SAP_type <= 6) {
+      GST_LOG (" - %s: %u", property, prop_SAP_type);
+    } else {
+      GST_WARNING
+          ("failed to parse unsigned integer property %s from xml string %s",
+          property, prop_string);
+    }
+    xmlFree (prop_string);
+  }
+
+  return (GstSAPType) prop_SAP_type;
+}
+
+static GstRange *
+gst_mpdparser_get_xml_prop_range (xmlNode * a_node, const gchar * property)
+{
+  xmlChar *prop_string;
+  GstRange *prop_range = NULL;
+  guint64 first_byte_pos = 0, last_byte_pos = 0;
+  guint len, pos;
+  gchar *str;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    len = xmlStrlen (prop_string);
+    str = (gchar *) prop_string;
+    GST_TRACE ("range: %s, len %d", str, len);
+
+    /* read "-" */
+    pos = strcspn (str, "-");
+    if (pos >= len) {
+      GST_TRACE ("pos %d >= len %d", pos, len);
+      goto error;
+    }
+    /* read first_byte_pos */
+    if (pos != 0) {
+      if (sscanf (str, "%llu", &first_byte_pos) != 1) {
+        goto error;
+      }
+    }
+    /* read last_byte_pos */
+    if (pos < (len - 1)) {
+      if (sscanf (str + pos + 1, "%llu", &last_byte_pos) != 1) {
+        goto error;
+      }
+    }
+    /* malloc return data structure */
+    prop_range = g_slice_new0 (GstRange);
+    if (prop_range == NULL) {
+      GST_WARNING ("Allocation of GstRange failed!");
+      goto error;
+    }
+    prop_range->first_byte_pos = first_byte_pos;
+    prop_range->last_byte_pos = last_byte_pos;
+    GST_LOG (" - %s: %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT,
+        property, first_byte_pos, last_byte_pos);
+    xmlFree (prop_string);
+  }
+
+  return prop_range;
+
+error:
+  GST_WARNING ("failed to parse property %s from xml string %s", property,
+      prop_string);
+  return NULL;
+}
+
+static GstRatio *
+gst_mpdparser_get_xml_prop_ratio (xmlNode * a_node, const gchar * property)
+{
+  xmlChar *prop_string;
+  GstRatio *prop_ratio = NULL;
+  guint num = 0, den = 1;
+  guint len, pos;
+  gchar *str;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    len = xmlStrlen (prop_string);
+    str = (gchar *) prop_string;
+    GST_TRACE ("ratio: %s, len %d", str, len);
+
+    /* read ":" */
+    pos = strcspn (str, ":");
+    if (pos >= len) {
+      GST_TRACE ("pos %d >= len %d", pos, len);
+      goto error;
+    }
+    /* read num */
+    if (pos != 0) {
+      if (sscanf (str, "%u", &num) != 1) {
+        goto error;
+      }
+    }
+    /* read den */
+    if (pos < (len - 1)) {
+      if (sscanf (str + pos + 1, "%u", &den) != 1) {
+        goto error;
+      }
+    }
+    /* malloc return data structure */
+    prop_ratio = g_slice_new0 (GstRatio);
+    if (prop_ratio == NULL) {
+      GST_WARNING ("Allocation of GstRatio failed!");
+      goto error;
+    }
+    prop_ratio->num = num;
+    prop_ratio->den = den;
+    GST_LOG (" - %s: %u:%u", property, num, den);
+    xmlFree (prop_string);
+  }
+
+  return prop_ratio;
+
+error:
+  GST_WARNING ("failed to parse property %s from xml string %s", property,
+      prop_string);
+  return NULL;
+}
+
+static GstFrameRate *
+gst_mpdparser_get_xml_prop_framerate (xmlNode * a_node, const gchar * property)
+{
+  xmlChar *prop_string;
+  GstFrameRate *prop_framerate = NULL;
+  guint num = 0, den = 1;
+  guint len, pos;
+  gchar *str;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    len = xmlStrlen (prop_string);
+    str = (gchar *) prop_string;
+    GST_TRACE ("framerate: %s, len %d", str, len);
+
+    /* read "/" if available */
+    pos = strcspn (str, "/");
+    /* read num */
+    if (pos != 0) {
+      if (sscanf (str, "%u", &num) != 1) {
+        goto error;
+      }
+    }
+    /* read den (if available) */
+    if (pos < (len - 1)) {
+      if (sscanf (str + pos + 1, "%u", &den) != 1) {
+        goto error;
+      }
+    }
+    /* alloc return data structure */
+    prop_framerate = g_slice_new0 (GstFrameRate);
+    if (prop_framerate == NULL) {
+      GST_WARNING ("Allocation of GstFrameRate failed!");
+      goto error;
+    }
+    prop_framerate->num = num;
+    prop_framerate->den = den;
+    if (den == 1)
+      GST_LOG (" - %s: %u", property, num);
+    else
+      GST_LOG (" - %s: %u/%u", property, num, den);
+    xmlFree (prop_string);
+  }
+
+  return prop_framerate;
+
+error:
+  GST_WARNING ("failed to parse property %s from xml string %s", property,
+      prop_string);
+  return NULL;
+}
+
+static GstConditionalUintType *
+gst_mpdparser_get_xml_prop_cond_uint (xmlNode * a_node, const gchar * property)
+{
+  xmlChar *prop_string;
+  GstConditionalUintType *prop_cond_uint = NULL;
+  gchar *str;
+  gboolean flag;
+  guint val;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    str = (gchar *) prop_string;
+    GST_TRACE ("conditional uint: %s", str);
+
+    if (strcmp (str, "false") == 0) {
+      flag = FALSE;
+      val = 0;
+    } else if (strcmp (str, "true") == 0) {
+      flag = TRUE;
+      val = 0;
+    } else {
+      flag = TRUE;
+      if (sscanf (str, "%u", &val) != 1)
+        goto error;
+    }
+
+    /* alloc return data structure */
+    prop_cond_uint = g_slice_new0 (GstConditionalUintType);
+    if (prop_cond_uint == NULL) {
+      GST_WARNING ("Allocation of GstConditionalUintType failed!");
+      goto error;
+    }
+    prop_cond_uint->flag = flag;
+    prop_cond_uint->value = val;
+    GST_LOG (" - %s: flag=%s val=%u", property, flag ? "true" : "false", val);
+    xmlFree (prop_string);
+  }
+
+  return prop_cond_uint;
+
+error:
+  GST_WARNING ("failed to parse property %s from xml string %s", property,
+      prop_string);
+  return NULL;
+}
+
+/*
+  DateTime Data Type
+
+  The dateTime data type is used to specify a date and a time.
+
+  The dateTime is specified in the following form "YYYY-MM-DDThh:mm:ss" where:
+
+    * YYYY indicates the year
+    * MM indicates the month
+    * DD indicates the day
+    * T indicates the start of the required time section
+    * hh indicates the hour
+    * mm indicates the minute
+    * ss indicates the second
+
+  Note: All components are required!
+*/
+
+static GstDateTime *
+gst_mpdparser_get_xml_prop_dateTime (xmlNode * a_node, const gchar * property)
+{
+  xmlChar *prop_string;
+  gchar *str;
+  gint ret, len, pos;
+  gint year, month, day, hour, minute, second;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    len = xmlStrlen (prop_string);
+    str = (gchar *) prop_string;
+    GST_TRACE ("dateTime: %s, len %d", str, len);
+    /* parse year */
+    ret = sscanf (str, "%d", &year);
+    if (ret != 1)
+      goto error;
+    pos = strcspn (str, "-");
+    str += (pos + 1);
+    GST_TRACE (" - year %d", year);
+    /* parse month */
+    ret = sscanf (str, "%d", &month);
+    if (ret != 1)
+      goto error;
+    pos = strcspn (str, "-");
+    str += (pos + 1);
+    GST_TRACE (" - month %d", month);
+    /* parse day */
+    ret = sscanf (str, "%d", &day);
+    if (ret != 1)
+      goto error;
+    pos = strcspn (str, "T");
+    str += (pos + 1);
+    GST_TRACE (" - day %d", day);
+    /* parse hour */
+    ret = sscanf (str, "%d", &hour);
+    if (ret != 1)
+      goto error;
+    pos = strcspn (str, ":");
+    str += (pos + 1);
+    GST_TRACE (" - hour %d", hour);
+    /* parse minute */
+    ret = sscanf (str, "%d", &minute);
+    if (ret != 1)
+      goto error;
+    pos = strcspn (str, ":");
+    str += (pos + 1);
+    GST_TRACE (" - minute %d", minute);
+    /* parse second */
+    ret = sscanf (str, "%d", &second);
+    if (ret != 1)
+      goto error;
+    GST_TRACE (" - second %d", second);
+
+    GST_LOG (" - %s: %4d/%02d/%02d %02d:%02d:%02d", property,
+        year, month, day, hour, minute, second);
+
+    return gst_date_time_new (0, year, month, day, hour, minute, second);
+  }
+
+  return NULL;
+
+error:
+  GST_WARNING ("failed to parse property %s from xml string %s", property,
+      prop_string);
+  return NULL;
+}
+
+/*
+  Duration Data Type
+
+  The duration data type is used to specify a time interval.
+
+  The time interval is specified in the following form "-PnYnMnDTnHnMnS" where:
+
+    * - indicates the negative sign (optional)
+    * P indicates the period (required)
+    * nY indicates the number of years
+    * nM indicates the number of months
+    * nD indicates the number of days
+    * T indicates the start of a time section (required if you are going to specify hours, minutes, or seconds)
+    * nH indicates the number of hours
+    * nM indicates the number of minutes
+    * nS indicates the number of seconds
+*/
+
+/* this function computes decimals * 10 ^ (3 - pos) */
+static gint
+convert_to_millisecs (gint decimals, gint pos)
+{
+  gint num = 1, den = 1, i = 3 - pos;
+
+  while (i < 0) {
+    den *= 10;
+    i++;
+  }
+  while (i > 0) {
+    num *= 10;
+    i--;
+  }
+  /* if i == 0 we have exactly 3 decimals and nothing to do */
+  return decimals * num / den;
+}
+
+static gint64
+gst_mpdparser_get_xml_prop_duration (xmlNode * a_node, const gchar * property)
+{
+  xmlChar *prop_string;
+  gchar *str;
+  gint64 prop_duration = -1;
+  gint ret, read, len, pos, posT;
+  gint years = 0, months = 0, days = 0, hours = 0, minutes = 0, seconds =
+      0, decimals = 0;
+  gint sign = 1;
+  gboolean have_ms = FALSE;
+
+  prop_string = xmlGetProp (a_node, (const xmlChar *) property);
+  if (prop_string) {
+    len = xmlStrlen (prop_string);
+    str = (gchar *) prop_string;
+    GST_TRACE ("duration: %s, len %d", str, len);
+    /* read "-" for sign, if present */
+    pos = strcspn (str, "-");
+    if (pos < len) {            /* found "-" */
+      if (pos != 0) {
+        GST_WARNING ("sign \"-\" non at the beginning of the string");
+        return -1;
+      }
+      GST_TRACE ("found - sign at the beginning");
+      sign = -1;
+      str++;
+      len--;
+    }
+    /* read "P" for period */
+    pos = strcspn (str, "P");
+    if (pos != 0) {
+      GST_WARNING ("P not found at the beginning of the string!");
+      return -1;
+    }
+    str++;
+    len--;
+    /* read "T" for time (if present) */
+    posT = strcspn (str, "T");
+    len -= posT;
+    if (posT > 0) {
+      /* there is some room between P and T, so there must be a period section */
+      /* read years, months, days */
+      do {
+        GST_TRACE ("parsing substring %s", str);
+        pos = strcspn (str, "YMD");
+        ret = sscanf (str, "%d", &read);
+        if (ret != 1) {
+          GST_WARNING ("can not read integer value from string %s!", str);
+          return -1;
+        }
+        switch (str[pos]) {
+          case 'Y':
+            years = read;
+            break;
+          case 'M':
+            months = read;
+            break;
+          case 'D':
+            days = read;
+            break;
+          default:
+            GST_WARNING ("unexpected char %c!", str[pos]);
+            return -1;
+            break;
+        }
+        GST_TRACE ("read number %d type %c", read, str[pos]);
+        str += (pos + 1);
+        posT -= (pos + 1);
+      } while (posT > 0);
+
+      GST_TRACE ("Y:M:D=%d:%d:%d", years, months, days);
+    }
+    /* read "T" for time (if present) */
+    /* here T is at pos == 0 */
+    str++;
+    len--;
+    pos = 0;
+    if (pos < len) {
+      /* T found, there is a time section */
+      /* read hours, minutes, seconds, cents of second */
+      do {
+        GST_TRACE ("parsing substring %s", str);
+        pos = strcspn (str, "HMS,.");
+        ret = sscanf (str, "%d", &read);
+        if (ret != 1) {
+          GST_WARNING ("can not read integer value from string %s!", str);
+          return -1;
+        }
+        switch (str[pos]) {
+          case 'H':
+            hours = read;
+            break;
+          case 'M':
+            minutes = read;
+            break;
+          case 'S':
+            if (have_ms) {
+              /* we have read the decimal part of the seconds */
+              decimals = convert_to_millisecs (read, pos);
+              GST_TRACE ("decimal number %d (%d digits) -> %d ms", read, pos,
+                  decimals);
+            } else {
+              /* no decimals */
+              seconds = read;
+            }
+            break;
+          case '.':
+          case ',':
+            /* we have read the integer part of a decimal number in seconds */
+            seconds = read;
+            have_ms = TRUE;
+            break;
+          default:
+            GST_WARNING ("unexpected char %c!", str[pos]);
+            return -1;
+            break;
+        }
+        GST_TRACE ("read number %d type %c", read, str[pos]);
+        str += pos + 1;
+        len -= (pos + 1);
+      } while (len > 0);
+
+      GST_TRACE ("H:M:S.MS=%d:%d:%d.%03d", hours, minutes, seconds, decimals);
+    }
+
+    xmlFree (prop_string);
+    prop_duration =
+        sign * ((((((gint64) years * 365 + months * 30 + days) * 24 +
+                    hours) * 60 + minutes) * 60 + seconds) * 1000 + decimals);
+    GST_LOG (" - %s: %" G_GINT64_FORMAT, property, prop_duration);
+  }
+
+  return prop_duration;
+}
+
+static gchar *
+gst_mpdparser_get_xml_node_content (xmlNode * a_node)
+{
+  xmlChar *content = NULL;
+
+  content = xmlNodeGetContent (a_node);
+  if (content) {
+    GST_LOG (" - %s: %s", a_node->name, content);
+  }
+
+  return (gchar *) content;
+}
+
+static gchar *
+gst_mpdparser_get_xml_node_namespace (xmlNode * a_node, const gchar * prefix)
+{
+  xmlNs *curr_ns;
+  gchar *namespace = NULL;
+
+  if (prefix == NULL) {
+    /* return the default namespace */
+    namespace = g_strdup ((gchar *) a_node->ns->href);
+    if (namespace) {
+      GST_LOG (" - default namespace: %s", namespace);
+    }
+  } else {
+    /* look for the specified prefix in the namespace list */
+    for (curr_ns = a_node->ns; curr_ns; curr_ns = curr_ns->next) {
+      if (xmlStrcmp (curr_ns->prefix, (xmlChar *) prefix) == 0) {
+        namespace = g_strdup ((gchar *) curr_ns->href);
+        if (namespace) {
+          GST_LOG (" - %s namespace: %s", curr_ns->prefix, curr_ns->href);
+        }
+      }
+    }
+  }
+
+  return namespace;
+}
+
+static void
+gst_mpdparser_parse_baseURL_node (GList ** list, xmlNode * a_node)
+{
+  GstBaseURL *new_base_url;
+
+  new_base_url = g_slice_new0 (GstBaseURL);
+  if (new_base_url == NULL) {
+    GST_WARNING ("Allocation of BaseURL node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_base_url);
+
+  GST_LOG ("content of BaseURL node:");
+  new_base_url->baseURL = gst_mpdparser_get_xml_node_content (a_node);
+  GST_LOG ("attributes of BaseURL node:");
+  new_base_url->serviceLocation =
+      gst_mpdparser_get_xml_prop_string (a_node, "serviceLocation");
+  new_base_url->byteRange =
+      gst_mpdparser_get_xml_prop_string (a_node, "byteRange");
+}
+
+static void
+gst_mpdparser_parse_descriptor_type_node (GList ** list, xmlNode * a_node)
+{
+  GstDescriptorType *new_descriptor;
+
+  new_descriptor = g_slice_new0 (GstDescriptorType);
+  if (new_descriptor == NULL) {
+    GST_WARNING ("Allocation of DescriptorType node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_descriptor);
+
+  GST_LOG ("attributes of %s node:", a_node->name);
+  new_descriptor->schemeIdUri =
+      gst_mpdparser_get_xml_prop_string (a_node, "schemeIdUri");
+  new_descriptor->value = gst_mpdparser_get_xml_prop_string (a_node, "value");
+
+ /* For adding ContentProtection to caps , get string of <mspr:pro> */
+  if(xmlStrcmp (a_node->name,(xmlChar *) "ContentProtection") == 0) {
+    if (a_node->children->next){
+      if(xmlStrcmp (a_node->children->next->name,(xmlChar *) "pro") == 0){
+        if (a_node->children->next->type == XML_ELEMENT_NODE) {
+          new_descriptor->msprPro = gst_mpdparser_get_xml_node_content (a_node->children->next);
+          }
+        }
+      }
+    }
+}
+
+static void
+gst_mpdparser_parse_content_component_node (GList ** list, xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstContentComponentNode *new_content_component;
+
+  new_content_component = g_slice_new0 (GstContentComponentNode);
+  if (new_content_component == NULL) {
+    GST_WARNING ("Allocation of ContentComponent node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_content_component);
+
+  GST_LOG ("attributes of ContentComponent node:");
+  new_content_component->id =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "id", 0);
+  new_content_component->lang =
+      gst_mpdparser_get_xml_prop_string (a_node, "lang");
+  new_content_component->contentType =
+      gst_mpdparser_get_xml_prop_string (a_node, "contentType");
+  new_content_component->par = gst_mpdparser_get_xml_prop_ratio (a_node, "par");
+
+  /* explore children nodes */
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "Accessibility") == 0) {
+        gst_mpdparser_parse_descriptor_type_node (&new_content_component->
+            Accessibility, cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Role") == 0) {
+        gst_mpdparser_parse_descriptor_type_node (&new_content_component->Role,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Rating") == 0) {
+        gst_mpdparser_parse_descriptor_type_node (&new_content_component->
+            Rating, cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Viewpoint") == 0) {
+        gst_mpdparser_parse_descriptor_type_node (&new_content_component->
+            Viewpoint, cur_node);
+      }
+    }
+  }
+}
+
+static void
+gst_mpdparser_parse_location_node (GList ** list, xmlNode * a_node)
+{
+  gchar *location;
+
+  GST_LOG ("content of Location node:");
+  location = gst_mpdparser_get_xml_node_content (a_node);
+
+  *list = g_list_append (*list, location);
+}
+
+static void
+gst_mpdparser_parse_subrepresentation_node (GList ** list, xmlNode * a_node)
+{
+  GstSubRepresentationNode *new_subrep;
+
+  new_subrep = g_slice_new0 (GstSubRepresentationNode);
+  if (new_subrep == NULL) {
+    GST_WARNING ("Allocation of SubRepresentation node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_subrep);
+
+  GST_LOG ("attributes of SubRepresentation node:");
+  new_subrep->level =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "level", 0);
+  new_subrep->dependencyLevel =
+      gst_mpdparser_get_xml_prop_uint_vector_type (a_node, "dependencyLevel",
+      &new_subrep->size);
+  new_subrep->bandwidth =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "bandwidth", 0);
+  new_subrep->contentComponent =
+      gst_mpdparser_get_xml_prop_string_vector_type (a_node,
+      "contentComponent");
+
+  /* RepresentationBase extension */
+  gst_mpdparser_parse_representation_base_type (&new_subrep->RepresentationBase,
+      a_node);
+}
+
+static void
+gst_mpdparser_parse_segment_url_node (GList ** list, xmlNode * a_node)
+{
+  GstSegmentURLNode *new_segment_url;
+
+  new_segment_url = g_slice_new0 (GstSegmentURLNode);
+  if (new_segment_url == NULL) {
+    GST_WARNING ("Allocation of SegmentURL node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_segment_url);
+
+  GST_LOG ("attributes of SegmentURL node:");
+  new_segment_url->media = gst_mpdparser_get_xml_prop_string (a_node, "media");
+  new_segment_url->mediaRange =
+      gst_mpdparser_get_xml_prop_range (a_node, "mediaRange");
+  new_segment_url->index = gst_mpdparser_get_xml_prop_string (a_node, "index");
+  new_segment_url->indexRange =
+      gst_mpdparser_get_xml_prop_range (a_node, "indexRange");
+}
+
+static void
+gst_mpdparser_parse_url_type_node (GstURLType ** pointer, xmlNode * a_node)
+{
+  GstURLType *new_url_type;
+
+  gst_mpdparser_free_url_type_node (*pointer);
+  *pointer = new_url_type = g_slice_new0 (GstURLType);
+  if (new_url_type == NULL) {
+    GST_WARNING ("Allocation of URLType node failed!");
+    return;
+  }
+
+  GST_LOG ("attributes of URLType node:");
+  new_url_type->sourceURL =
+      gst_mpdparser_get_xml_prop_string (a_node, "sourceURL");
+  new_url_type->range = gst_mpdparser_get_xml_prop_range (a_node, "range");
+}
+
+static void
+gst_mpdparser_parse_seg_base_type_ext (GstSegmentBaseType ** pointer,
+    xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstSegmentBaseType *seg_base_type;
+
+  gst_mpdparser_free_seg_base_type_ext (*pointer);
+  *pointer = seg_base_type = g_slice_new0 (GstSegmentBaseType);
+  if (seg_base_type == NULL) {
+    GST_WARNING ("Allocation of SegmentBaseType node failed!");
+    return;
+  }
+
+  GST_LOG ("attributes of SegmentBaseType extension:");
+  seg_base_type->timescale =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "timescale", 0);
+  seg_base_type->presentationTimeOffset =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node,
+      "presentationTimeOffset", 0);
+  seg_base_type->indexRange =
+      gst_mpdparser_get_xml_prop_string (a_node, "indexRange");
+  seg_base_type->indexRangeExact =
+      gst_mpdparser_get_xml_prop_boolean (a_node, "indexRangeExact");
+
+  /* explore children nodes */
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "Initialization") == 0 ||
+          xmlStrcmp (cur_node->name, (xmlChar *) "Initialisation") == 0) {
+        gst_mpdparser_parse_url_type_node (&seg_base_type->Initialization,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name,
+              (xmlChar *) "RepresentationIndex") == 0) {
+        gst_mpdparser_parse_url_type_node (&seg_base_type->RepresentationIndex,
+            cur_node);
+      }
+    }
+  }
+}
+
+static void
+gst_mpdparser_parse_s_node (GList ** list, xmlNode * a_node)
+{
+  GstSNode *new_s_node;
+
+  new_s_node = g_slice_new0 (GstSNode);
+  if (new_s_node == NULL) {
+    GST_WARNING ("Allocation of S node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_s_node);
+
+  GST_LOG ("attributes of S node:");
+  new_s_node->t = gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "t", 0);
+  new_s_node->d = gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "d", 0);
+  new_s_node->r = gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "r", 0);
+}
+
+static void
+gst_mpdparser_parse_segment_timeline_node (GstSegmentTimelineNode ** pointer,
+    xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstSegmentTimelineNode *new_seg_timeline;
+
+  gst_mpdparser_free_segment_timeline_node (*pointer);
+  *pointer = new_seg_timeline = g_slice_new0 (GstSegmentTimelineNode);
+  if (new_seg_timeline == NULL) {
+    GST_WARNING ("Allocation of SegmentTimeline node failed!");
+    return;
+  }
+
+  /* explore children nodes */
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "S") == 0) {
+        gst_mpdparser_parse_s_node (&new_seg_timeline->S, cur_node);
+      }
+    }
+  }
+}
+
+static void
+gst_mpdparser_parse_mult_seg_base_type_ext (GstMultSegmentBaseType ** pointer,
+    xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstMultSegmentBaseType *mult_seg_base_type;
+
+  gst_mpdparser_free_mult_seg_base_type_ext (*pointer);
+  *pointer = mult_seg_base_type = g_slice_new0 (GstMultSegmentBaseType);
+  if (mult_seg_base_type == NULL) {
+    GST_WARNING ("Allocation of MultipleSegmentBaseType node failed!");
+    return;
+  }
+
+  GST_LOG ("attributes of MultipleSegmentBaseType extension:");
+  mult_seg_base_type->duration =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "duration", 0);
+  mult_seg_base_type->startNumber =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "startNumber", 1);
+
+  GST_LOG ("extension of MultipleSegmentBaseType extension:");
+  gst_mpdparser_parse_seg_base_type_ext (&mult_seg_base_type->SegBaseType,
+      a_node);
+
+  /* explore children nodes */
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentTimeline") == 0) {
+        gst_mpdparser_parse_segment_timeline_node (&mult_seg_base_type->
+            SegmentTimeline, cur_node);
+      } else if (xmlStrcmp (cur_node->name,
+              (xmlChar *) "BitstreamSwitching") == 0) {
+        gst_mpdparser_parse_url_type_node (&mult_seg_base_type->
+            BitstreamSwitching, cur_node);
+      }
+    }
+  }
+}
+
+static void
+gst_mpdparser_parse_segment_list_node (GstSegmentListNode ** pointer,
+    xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstSegmentListNode *new_segment_list;
+
+  gst_mpdparser_free_segment_list_node (*pointer);
+  *pointer = new_segment_list = g_slice_new0 (GstSegmentListNode);
+  if (new_segment_list == NULL) {
+    GST_WARNING ("Allocation of SegmentList node failed!");
+    return;
+  }
+
+  GST_LOG ("extension of SegmentList node:");
+  gst_mpdparser_parse_mult_seg_base_type_ext (&new_segment_list->
+      MultSegBaseType, a_node);
+
+  /* explore children nodes */
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentURL") == 0) {
+        gst_mpdparser_parse_segment_url_node (&new_segment_list->SegmentURL,
+            cur_node);
+      }
+    }
+  }
+}
+
+static void
+gst_mpdparser_parse_representation_base_type (GstRepresentationBaseType **
+    pointer, xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstRepresentationBaseType *representation_base;
+
+  gst_mpdparser_free_representation_base_type (*pointer);
+  *pointer = representation_base = g_slice_new0 (GstRepresentationBaseType);
+  if (representation_base == NULL) {
+    GST_WARNING ("Allocation of RepresentationBaseType node failed!");
+    return;
+  }
+
+  GST_LOG ("attributes of RepresentationBaseType extension:");
+  representation_base->profiles =
+      gst_mpdparser_get_xml_prop_string (a_node, "profiles");
+  representation_base->width =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "width", 0);
+  representation_base->height =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "height", 0);
+  representation_base->bandwidth =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "bandwidth", 0);
+  representation_base->sar = gst_mpdparser_get_xml_prop_ratio (a_node, "sar");
+  representation_base->frameRate =
+      gst_mpdparser_get_xml_prop_framerate (a_node, "frameRate");
+  representation_base->audioSamplingRate =
+      gst_mpdparser_get_xml_prop_string (a_node, "audioSamplingRate");
+  representation_base->mimeType =
+      gst_mpdparser_get_xml_prop_string (a_node, "mimeType");
+  representation_base->segmentProfiles =
+      gst_mpdparser_get_xml_prop_string (a_node, "segmentProfiles");
+  representation_base->codecs =
+      gst_mpdparser_get_xml_prop_string (a_node, "codecs");
+  representation_base->maximumSAPPeriod =
+      gst_mpdparser_get_xml_prop_double (a_node, "maximumSAPPeriod");
+  representation_base->startWithSAP =
+      gst_mpdparser_get_xml_prop_SAP_type (a_node, "startWithSAP");
+  representation_base->maxPlayoutRate =
+      gst_mpdparser_get_xml_prop_double (a_node, "maxPlayoutRate");
+  representation_base->codingDependency =
+      gst_mpdparser_get_xml_prop_boolean (a_node, "codingDependency");
+  representation_base->scanType =
+      gst_mpdparser_get_xml_prop_string (a_node, "scanType");
+
+  /* explore children nodes */
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "FramePacking") == 0) {
+        gst_mpdparser_parse_descriptor_type_node (&representation_base->
+            FramePacking, cur_node);
+      } else if (xmlStrcmp (cur_node->name,
+              (xmlChar *) "AudioChannelConfiguration") == 0) {
+        gst_mpdparser_parse_descriptor_type_node (&representation_base->
+            AudioChannelConfiguration, cur_node);
+      } else if (xmlStrcmp (cur_node->name,
+              (xmlChar *) "ContentProtection") == 0) {
+        gst_mpdparser_parse_descriptor_type_node (&representation_base->
+            ContentProtection, cur_node);
+      }
+    }
+  }
+}
+
+static void
+gst_mpdparser_parse_representation_node (GList ** list, xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstRepresentationNode *new_representation;
+
+  new_representation = g_slice_new0 (GstRepresentationNode);
+  if (new_representation == NULL) {
+    GST_WARNING ("Allocation of Representation node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_representation);
+
+  GST_LOG ("attributes of Representation node:");
+  new_representation->id = gst_mpdparser_get_xml_prop_string (a_node, "id");
+  new_representation->bandwidth =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "bandwidth", 0);
+  new_representation->qualityRanking =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "qualityRanking", 0);
+  new_representation->dependencyId =
+      gst_mpdparser_get_xml_prop_string_vector_type (a_node, "dependencyId");
+  new_representation->mediaStreamStructureId =
+      gst_mpdparser_get_xml_prop_string_vector_type (a_node,
+      "mediaStreamStructureId");
+
+  /* RepresentationBase extension */
+  gst_mpdparser_parse_representation_base_type (&new_representation->
+      RepresentationBase, a_node);
+
+  /* explore children nodes */
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentBase") == 0) {
+        gst_mpdparser_parse_seg_base_type_ext (&new_representation->SegmentBase,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentTemplate") == 0) {
+        gst_mpdparser_parse_segment_template_node (&new_representation->
+            SegmentTemplate, cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentList") == 0) {
+        gst_mpdparser_parse_segment_list_node (&new_representation->SegmentList,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "BaseURL") == 0) {
+        gst_mpdparser_parse_baseURL_node (&new_representation->BaseURLs,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name,
+              (xmlChar *) "SubRepresentation") == 0) {
+        gst_mpdparser_parse_subrepresentation_node (&new_representation->
+            SubRepresentations, cur_node);
+      }
+    }
+  }
+}
+
+static void
+gst_mpdparser_parse_adaptation_set_node (GList ** list, xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstAdaptationSetNode *new_adap_set;
+
+  new_adap_set = g_slice_new0 (GstAdaptationSetNode);
+  if (new_adap_set == NULL) {
+    GST_WARNING ("Allocation of AdaptationSet node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_adap_set);
+
+  GST_LOG ("attributes of AdaptationSet node:");
+  new_adap_set->id =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "id", 0);
+  new_adap_set->group =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "group", 0);
+  new_adap_set->lang = gst_mpdparser_get_xml_prop_string (a_node, "lang");
+  new_adap_set->contentType =
+      gst_mpdparser_get_xml_prop_string (a_node, "contentType");
+  new_adap_set->par = gst_mpdparser_get_xml_prop_ratio (a_node, "par");
+  new_adap_set->minBandwidth =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "minBandwidth", 0);
+  new_adap_set->maxBandwidth =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "maxBandwidth", 0);
+  new_adap_set->minWidth =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "minWidth", 0);
+  new_adap_set->maxWidth =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "maxWidth", 0);
+  new_adap_set->minHeight =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "minHeight", 0);
+  new_adap_set->maxHeight =
+      gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "maxHeight", 0);
+  new_adap_set->minFrameRate =
+      gst_mpdparser_get_xml_prop_framerate (a_node, "minFrameRate");
+  new_adap_set->maxFrameRate =
+      gst_mpdparser_get_xml_prop_framerate (a_node, "maxFrameRate");
+  new_adap_set->segmentAlignment =
+      gst_mpdparser_get_xml_prop_cond_uint (a_node, "segmentAlignment");
+  new_adap_set->subsegmentAlignment =
+      gst_mpdparser_get_xml_prop_cond_uint (a_node, "subsegmentAlignment");
+  new_adap_set->subsegmentStartsWithSAP =
+      gst_mpdparser_get_xml_prop_SAP_type (a_node, "subsegmentStartsWithSAP");
+  new_adap_set->bitstreamSwitching =
+      gst_mpdparser_get_xml_prop_boolean (a_node, "bitstreamSwitching");
+
+  /* RepresentationBase extension */
+  gst_mpdparser_parse_representation_base_type (&new_adap_set->
+      RepresentationBase, a_node);
+
+  /* explore children nodes */
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "Accessibility") == 0) {
+        gst_mpdparser_parse_descriptor_type_node (&new_adap_set->Accessibility,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Role") == 0) {
+        gst_mpdparser_parse_descriptor_type_node (&new_adap_set->Role,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Rating") == 0) {
+        gst_mpdparser_parse_descriptor_type_node (&new_adap_set->Rating,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Viewpoint") == 0) {
+        gst_mpdparser_parse_descriptor_type_node (&new_adap_set->Viewpoint,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Representation") == 0) {
+        gst_mpdparser_parse_representation_node (&new_adap_set->Representations,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "BaseURL") == 0) {
+        gst_mpdparser_parse_baseURL_node (&new_adap_set->BaseURLs, cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentBase") == 0) {
+        gst_mpdparser_parse_seg_base_type_ext (&new_adap_set->SegmentBase,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentList") == 0) {
+        gst_mpdparser_parse_segment_list_node (&new_adap_set->SegmentList,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name,
+              (xmlChar *) "ContentComponent") == 0) {
+        gst_mpdparser_parse_content_component_node (&new_adap_set->
+            ContentComponents, cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentTemplate") == 0) {
+        gst_mpdparser_parse_segment_template_node (&new_adap_set->
+            SegmentTemplate, cur_node);
+      }
+    }
+  }
+}
+
+static void
+gst_mpdparser_parse_subset_node (GList ** list, xmlNode * a_node)
+{
+  GstSubsetNode *new_subset;
+
+  new_subset = g_slice_new0 (GstSubsetNode);
+  if (new_subset == NULL) {
+    GST_WARNING ("Allocation of Subset node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_subset);
+
+  GST_LOG ("attributes of Subset node:");
+  new_subset->contains =
+      gst_mpdparser_get_xml_prop_uint_vector_type (a_node, "contains",
+      &new_subset->size);
+}
+
+static void
+gst_mpdparser_parse_segment_template_node (GstSegmentTemplateNode ** pointer,
+    xmlNode * a_node)
+{
+  GstSegmentTemplateNode *new_segment_template;
+
+  gst_mpdparser_free_segment_template_node (*pointer);
+  *pointer = new_segment_template = g_slice_new0 (GstSegmentTemplateNode);
+  if (new_segment_template == NULL) {
+    GST_WARNING ("Allocation of SegmentTemplate node failed!");
+    return;
+  }
+
+  GST_LOG ("extension of SegmentTemplate node:");
+  gst_mpdparser_parse_mult_seg_base_type_ext (&new_segment_template->
+      MultSegBaseType, a_node);
+
+  GST_LOG ("attributes of SegmentTemplate node:");
+  new_segment_template->media =
+      gst_mpdparser_get_xml_prop_string (a_node, "media");
+  new_segment_template->index =
+      gst_mpdparser_get_xml_prop_string (a_node, "index");
+  new_segment_template->initialization =
+      gst_mpdparser_get_xml_prop_string (a_node, "initialization");
+  new_segment_template->bitstreamSwitching =
+      gst_mpdparser_get_xml_prop_string (a_node, "bitstreamSwitching");
+}
+
+static void
+gst_mpdparser_parse_period_node (GList ** list, xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstPeriodNode *new_period;
+
+  new_period = g_slice_new0 (GstPeriodNode);
+  if (new_period == NULL) {
+    GST_WARNING ("Allocation of Period node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_period);
+
+  GST_LOG ("attributes of Period node:");
+  new_period->id = gst_mpdparser_get_xml_prop_string (a_node, "id");
+  new_period->start = gst_mpdparser_get_xml_prop_duration (a_node, "start");
+  new_period->duration =
+      gst_mpdparser_get_xml_prop_duration (a_node, "duration");
+  new_period->bitstreamSwitching =
+      gst_mpdparser_get_xml_prop_boolean (a_node, "bitstreamSwitching");
+
+  /* explore children nodes */
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "AdaptationSet") == 0) {
+        gst_mpdparser_parse_adaptation_set_node (&new_period->AdaptationSets,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentBase") == 0) {
+        gst_mpdparser_parse_seg_base_type_ext (&new_period->SegmentBase,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentList") == 0) {
+        gst_mpdparser_parse_segment_list_node (&new_period->SegmentList,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentTemplate") == 0) {
+        gst_mpdparser_parse_segment_template_node (&new_period->SegmentTemplate,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Subset") == 0) {
+        gst_mpdparser_parse_subset_node (&new_period->Subsets, cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "BaseURL") == 0) {
+        gst_mpdparser_parse_baseURL_node (&new_period->BaseURLs, cur_node);
+      }
+    }
+  }
+}
+
+static void
+gst_mpdparser_parse_program_info_node (GList ** list, xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstProgramInformationNode *new_prog_info;
+
+  new_prog_info = g_slice_new0 (GstProgramInformationNode);
+  if (new_prog_info == NULL) {
+    GST_WARNING ("Allocation of ProgramInfo node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_prog_info);
+
+  GST_LOG ("attributes of ProgramInformation node:");
+  new_prog_info->lang = gst_mpdparser_get_xml_prop_string (a_node, "lang");
+  new_prog_info->moreInformationURL =
+      gst_mpdparser_get_xml_prop_string (a_node, "moreInformationURL");
+
+  /* explore children nodes */
+  GST_LOG ("children of ProgramInformation node:");
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "Title") == 0) {
+        new_prog_info->Title = gst_mpdparser_get_xml_node_content (cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Source") == 0) {
+        new_prog_info->Source = gst_mpdparser_get_xml_node_content (cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Copyright") == 0) {
+        new_prog_info->Copyright =
+            gst_mpdparser_get_xml_node_content (cur_node);
+      }
+    }
+  }
+}
+
+static void
+gst_mpdparser_parse_metrics_range_node (GList ** list, xmlNode * a_node)
+{
+  GstMetricsRangeNode *new_metrics_range;
+
+  new_metrics_range = g_slice_new0 (GstMetricsRangeNode);
+  if (new_metrics_range == NULL) {
+    GST_WARNING ("Allocation of Metrics Range node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_metrics_range);
+
+  GST_LOG ("attributes of Metrics Range node:");
+  new_metrics_range->starttime =
+      gst_mpdparser_get_xml_prop_duration (a_node, "starttime");
+  new_metrics_range->duration =
+      gst_mpdparser_get_xml_prop_duration (a_node, "duration");
+}
+
+static void
+gst_mpdparser_parse_metrics_node (GList ** list, xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstMetricsNode *new_metrics;
+
+  new_metrics = g_slice_new0 (GstMetricsNode);
+  if (new_metrics == NULL) {
+    GST_WARNING ("Allocation of Metrics node failed!");
+    return;
+  }
+  *list = g_list_append (*list, new_metrics);
+
+  GST_LOG ("attributes of Metrics node:");
+  new_metrics->metrics = gst_mpdparser_get_xml_prop_string (a_node, "metrics");
+
+  /* explore children nodes */
+  GST_LOG ("children of Metrics node:");
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "Range") == 0) {
+        gst_mpdparser_parse_metrics_range_node (&new_metrics->MetricsRanges,
+            cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Reporting") == 0) {
+        /* No reporting scheme is specified in this part of ISO/IEC 23009.
+         * It is expected that external specifications may define formats
+         * and delivery for the reporting data. */
+        GST_LOG (" - Reporting node found (unknown structure)");
+      }
+    }
+  }
+}
+
+static void
+gst_mpdparser_parse_root_node (GstMPDNode ** pointer, xmlNode * a_node)
+{
+  xmlNode *cur_node;
+  GstMPDNode *new_mpd;
+
+  gst_mpdparser_free_mpd_node (*pointer);
+  *pointer = new_mpd = g_slice_new0 (GstMPDNode);
+  if (new_mpd == NULL) {
+    GST_WARNING ("Allocation of MPD node failed!");
+    return;
+  }
+
+  GST_LOG ("namespaces of root MPD node:");
+  new_mpd->default_namespace =
+      gst_mpdparser_get_xml_node_namespace (a_node, NULL);
+  new_mpd->namespace_xsi = gst_mpdparser_get_xml_node_namespace (a_node, "xsi");
+  new_mpd->namespace_ext = gst_mpdparser_get_xml_node_namespace (a_node, "ext");
+
+  GST_LOG ("attributes of root MPD node:");
+  new_mpd->schemaLocation =
+      gst_mpdparser_get_xml_prop_string (a_node, "schemaLocation");
+  new_mpd->id = gst_mpdparser_get_xml_prop_string (a_node, "id");
+  new_mpd->profiles = gst_mpdparser_get_xml_prop_string (a_node, "profiles");
+  new_mpd->type = gst_mpdparser_get_xml_prop_type (a_node, "type");
+  new_mpd->availabilityStartTime =
+      gst_mpdparser_get_xml_prop_dateTime (a_node, "availabilityStartTime");
+  new_mpd->availabilityEndTime =
+      gst_mpdparser_get_xml_prop_dateTime (a_node, "availabilityEndTime");
+  new_mpd->mediaPresentationDuration =
+      gst_mpdparser_get_xml_prop_duration (a_node, "mediaPresentationDuration");
+  new_mpd->minimumUpdatePeriod =
+      gst_mpdparser_get_xml_prop_duration (a_node, "minimumUpdatePeriod");
+  new_mpd->minBufferTime =
+      gst_mpdparser_get_xml_prop_duration (a_node, "minBufferTime");
+  new_mpd->timeShiftBufferDepth =
+      gst_mpdparser_get_xml_prop_duration (a_node, "timeShiftBufferDepth");
+  new_mpd->suggestedPresentationDelay =
+      gst_mpdparser_get_xml_prop_duration (a_node,
+      "suggestedPresentationDelay");
+  new_mpd->maxSegmentDuration =
+      gst_mpdparser_get_xml_prop_duration (a_node, "maxSegmentDuration");
+  new_mpd->maxSubsegmentDuration =
+      gst_mpdparser_get_xml_prop_duration (a_node, "maxSubsegmentDuration");
+
+  /* explore children Period nodes */
+  for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
+    if (cur_node->type == XML_ELEMENT_NODE) {
+      if (xmlStrcmp (cur_node->name, (xmlChar *) "Period") == 0) {
+        gst_mpdparser_parse_period_node (&new_mpd->Periods, cur_node);
+      } else if (xmlStrcmp (cur_node->name,
+              (xmlChar *) "ProgramInformation") == 0) {
+        gst_mpdparser_parse_program_info_node (&new_mpd->ProgramInfo, cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "BaseURL") == 0) {
+        gst_mpdparser_parse_baseURL_node (&new_mpd->BaseURLs, cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Location") == 0) {
+        gst_mpdparser_parse_location_node (&new_mpd->Locations, cur_node);
+      } else if (xmlStrcmp (cur_node->name, (xmlChar *) "Metrics") == 0) {
+        gst_mpdparser_parse_metrics_node (&new_mpd->Metrics, cur_node);
+      }
+    }
+  }
+}
+
+/* comparison functions */
+static int
+strncmp_ext (const char *s1, const char *s2)
+{
+  if (s1 == NULL && s2 == NULL)
+    return 0;
+  if (s1 == NULL && s2 != NULL)
+    return 1;
+  if (s2 == NULL && s1 != NULL)
+    return 1;
+  return strncmp (s1, s2, strlen (s2));
+}
+
+/* navigation functions */
+static GstAdaptationSetNode *
+gst_mpdparser_get_first_adapt_set_with_mimeType (GList * AdaptationSets,
+    const gchar * mimeType)
+{
+  GList *list;
+  GstAdaptationSetNode *adapt_set;
+
+  if (AdaptationSets == NULL)
+    return NULL;
+
+  for (list = g_list_first (AdaptationSets); list; list = g_list_next (list)) {
+    adapt_set = (GstAdaptationSetNode *) list->data;
+    if (adapt_set) {
+      gchar *this_mimeType = NULL;
+      GstRepresentationNode *rep;
+      rep =
+          gst_mpdparser_get_lowest_representation (adapt_set->Representations);
+      if (!rep) {
+        GST_WARNING ("No valid representation in the MPD file, aborting...");
+        return NULL;
+      }
+      if (rep->RepresentationBase)
+        this_mimeType = rep->RepresentationBase->mimeType;
+      if (!this_mimeType && adapt_set->RepresentationBase) {
+        this_mimeType = adapt_set->RepresentationBase->mimeType;
+      }
+      if (strncmp_ext (this_mimeType, mimeType) == 0)
+        return adapt_set;
+    }
+  }
+
+  return NULL;
+}
+
+/* if idx < 0, returns the highest adaptation set with the given mimeType
+ * if idx >= 0, returns the highest adaptation set with the given mimeType and an index <= idx
+ */
+static GstAdaptationSetNode *
+gst_mpdparser_get_adapt_set_with_mimeType_and_idx (GList * AdaptationSets,
+    const gchar * mimeType, gint idx)
+{
+  GList *list;
+  GstAdaptationSetNode *adapt_set, *selected = NULL;
+  gint i = 0;
+
+  if (AdaptationSets == NULL)
+    return NULL;
+
+  for (list = g_list_first (AdaptationSets); list; list = g_list_next (list)) {
+    adapt_set = (GstAdaptationSetNode *) list->data;
+    if (adapt_set) {
+      gchar *this_mimeType = NULL;
+      GstRepresentationNode *rep;
+      rep =
+          gst_mpdparser_get_lowest_representation (adapt_set->Representations);
+      if (!rep) {
+        GST_WARNING ("No valid representation in the MPD file, aborting...");
+        return NULL;
+      }
+      if (rep->RepresentationBase)
+        this_mimeType = rep->RepresentationBase->mimeType;
+      if (!this_mimeType && adapt_set->RepresentationBase) {
+        this_mimeType = adapt_set->RepresentationBase->mimeType;
+      }
+      if (strncmp_ext (this_mimeType, mimeType) == 0) {
+        if (idx < 0 || i <= idx)
+          selected = adapt_set;
+        i++;
+      }
+    }
+  }
+
+  return selected;
+}
+
+static GstAdaptationSetNode *
+gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang (GList *
+    AdaptationSets, const gchar * mimeType, const gchar * lang)
+{
+  GList *list;
+  GstAdaptationSetNode *adapt_set;
+
+  if (AdaptationSets == NULL)
+    return NULL;
+
+  for (list = g_list_first (AdaptationSets); list; list = g_list_next (list)) {
+    adapt_set = (GstAdaptationSetNode *) list->data;
+    if (adapt_set) {
+      GstRepresentationNode *rep;
+      gchar *this_lang = adapt_set->lang;
+      gchar *this_mimeType = NULL;
+      rep =
+          gst_mpdparser_get_lowest_representation (adapt_set->Representations);
+      if (!rep) {
+        GST_WARNING ("No valid representation in the MPD file, aborting...");
+        return NULL;
+      }
+      if (rep->RepresentationBase)
+        this_mimeType = rep->RepresentationBase->mimeType;
+      if (!this_mimeType && adapt_set->RepresentationBase) {
+        this_mimeType = adapt_set->RepresentationBase->mimeType;
+      }
+      if (strncmp_ext (this_mimeType, mimeType) == 0
+          && strncmp_ext (this_lang, lang) == 0)
+        return adapt_set;
+    }
+  }
+
+  return NULL;
+}
+
+static GstRepresentationNode *
+gst_mpdparser_get_lowest_representation (GList * Representations)
+{
+  GList *list = NULL;
+
+  if (Representations == NULL)
+    return NULL;
+
+  list = g_list_first (Representations);
+
+  return list ? (GstRepresentationNode *) list->data : NULL;
+}
+
+#if 0
+static GstRepresentationNode *
+gst_mpdparser_get_highest_representation (GList * Representations)
+{
+  GList *list = NULL;
+
+  if (Representations == NULL)
+    return NULL;
+
+  list = g_list_last (Representations);
+
+  return list ? (GstRepresentationNode *) list->data : NULL;
+}
+
+static GstRepresentationNode *
+gst_mpdparser_get_representation_with_max_bandwidth (GList * Representations,
+    gint max_bandwidth)
+{
+  GList *list = NULL;
+  GstRepresentationNode *representation, *best_rep = NULL;
+
+  if (Representations == NULL)
+    return NULL;
+
+  if (max_bandwidth <= 0)       /* 0 => get highest representation available */
+    return gst_mpdparser_get_highest_representation (Representations);
+
+  for (list = g_list_first (Representations); list; list = g_list_next (list)) {
+    representation = (GstRepresentationNode *) list->data;
+    if (representation && representation->bandwidth <= max_bandwidth) {
+      best_rep = representation;
+    }
+  }
+
+  return best_rep;
+}
+#endif
+
+static GstSegmentBaseType *
+gst_mpdparser_get_segment_base (GstPeriodNode * Period,
+    GstAdaptationSetNode * AdaptationSet,
+    GstRepresentationNode * Representation)
+{
+  GstSegmentBaseType *SegmentBase = NULL;
+
+  if (Representation && Representation->SegmentBase
+      && Representation->SegmentBase->Initialization) {
+    SegmentBase = Representation->SegmentBase;
+  } else if (AdaptationSet && AdaptationSet->SegmentBase
+      && AdaptationSet->SegmentBase->Initialization) {
+    SegmentBase = AdaptationSet->SegmentBase;
+  } else if (Period && Period->SegmentBase
+      && Period->SegmentBase->Initialization) {
+    SegmentBase = Period->SegmentBase;
+  }
+  /* the SegmentBase element could be encoded also inside a SegmentList element */
+  if (SegmentBase == NULL) {
+    if (Representation && Representation->SegmentList
+        && Representation->SegmentList->MultSegBaseType
+        && Representation->SegmentList->MultSegBaseType->SegBaseType
+        && Representation->SegmentList->MultSegBaseType->SegBaseType->
+        Initialization) {
+      SegmentBase = Representation->SegmentList->MultSegBaseType->SegBaseType;
+    } else if (AdaptationSet && AdaptationSet->SegmentList
+        && AdaptationSet->SegmentList->MultSegBaseType
+        && AdaptationSet->SegmentList->MultSegBaseType->SegBaseType
+        && AdaptationSet->SegmentList->MultSegBaseType->SegBaseType->
+        Initialization) {
+      SegmentBase = AdaptationSet->SegmentList->MultSegBaseType->SegBaseType;
+    } else if (Period && Period->SegmentList
+        && Period->SegmentList->MultSegBaseType
+        && Period->SegmentList->MultSegBaseType->SegBaseType
+        && Period->SegmentList->MultSegBaseType->SegBaseType->Initialization) {
+      SegmentBase = Period->SegmentList->MultSegBaseType->SegBaseType;
+    }
+  }
+
+  return SegmentBase;
+}
+
+gint
+gst_mpdparser_get_rep_idx_with_max_bandwidth (GList * Representations,
+    guint64 max_bandwidth)
+{
+  GList *list = NULL, *best = NULL;
+  GstRepresentationNode *representation;
+  guint64 best_bandwidth = 0;
+
+  GST_DEBUG ("max bandwidth %" G_GUINT64_FORMAT, max_bandwidth);
+
+  if (Representations == NULL)
+    return -1;
+
+  if (max_bandwidth <= 0)       /* 0 => get lowest representation available */
+    return 0;
+
+  for (list = g_list_first (Representations); list; list = g_list_next (list)) {
+    representation = (GstRepresentationNode *) list->data;
+    if (representation && representation->bandwidth <= max_bandwidth &&
+       representation->bandwidth > best_bandwidth) {
+      best = list;
+      best_bandwidth = representation->bandwidth;
+    }
+  }
+
+  return best ? g_list_position (Representations, best) : -1;
+}
+
+static GstSegmentListNode *
+gst_mpdparser_get_segment_list (GstPeriodNode * Period,
+    GstAdaptationSetNode * AdaptationSet,
+    GstRepresentationNode * Representation)
+{
+  GstSegmentListNode *SegmentList = NULL;
+
+  if (Representation && Representation->SegmentList) {
+    SegmentList = Representation->SegmentList;
+  } else if (AdaptationSet && AdaptationSet->SegmentList) {
+    SegmentList = AdaptationSet->SegmentList;
+  } else {
+    SegmentList = Period->SegmentList;
+  }
+
+  return SegmentList;
+}
+
+/* memory management functions */
+static void
+gst_mpdparser_free_mpd_node (GstMPDNode * mpd_node)
+{
+  if (mpd_node) {
+    g_free (mpd_node->default_namespace);
+    g_free (mpd_node->namespace_xsi);
+    g_free (mpd_node->namespace_ext);
+    g_free (mpd_node->schemaLocation);
+    g_free (mpd_node->id);
+    g_free (mpd_node->profiles);
+    if (mpd_node->availabilityStartTime)
+      gst_date_time_unref (mpd_node->availabilityStartTime);
+    if (mpd_node->availabilityEndTime)
+      gst_date_time_unref (mpd_node->availabilityEndTime);
+    g_list_foreach (mpd_node->ProgramInfo,
+        (GFunc) gst_mpdparser_free_prog_info_node, NULL);
+    g_list_free (mpd_node->ProgramInfo);
+    g_list_foreach (mpd_node->BaseURLs,
+        (GFunc) gst_mpdparser_free_base_url_node, NULL);
+    g_list_free (mpd_node->BaseURLs);
+    g_list_foreach (mpd_node->Locations, (GFunc) g_free, NULL);
+    g_list_free (mpd_node->Locations);
+    g_list_foreach (mpd_node->Periods, (GFunc) gst_mpdparser_free_period_node,
+        NULL);
+    g_list_free (mpd_node->Periods);
+    g_list_foreach (mpd_node->Metrics, (GFunc) gst_mpdparser_free_metrics_node,
+        NULL);
+    g_list_free (mpd_node->Metrics);
+    g_slice_free (GstMPDNode, mpd_node);
+  }
+}
+
+static void
+gst_mpdparser_free_prog_info_node (GstProgramInformationNode * prog_info_node)
+{
+  if (prog_info_node) {
+    g_free (prog_info_node->lang);
+    g_free (prog_info_node->moreInformationURL);
+    g_free (prog_info_node->Title);
+    g_free (prog_info_node->Source);
+    g_free (prog_info_node->Copyright);
+    g_slice_free (GstProgramInformationNode, prog_info_node);
+  }
+}
+
+static void
+gst_mpdparser_free_metrics_node (GstMetricsNode * metrics_node)
+{
+  if (metrics_node) {
+    g_free (metrics_node->metrics);
+    g_list_foreach (metrics_node->MetricsRanges,
+        (GFunc) gst_mpdparser_free_metrics_range_node, NULL);
+    g_list_free (metrics_node->MetricsRanges);
+  }
+}
+
+static void
+gst_mpdparser_free_metrics_range_node (GstMetricsRangeNode * metrics_range_node)
+{
+  if (metrics_range_node) {
+    g_slice_free (GstMetricsRangeNode, metrics_range_node);
+  }
+}
+
+static void
+gst_mpdparser_free_period_node (GstPeriodNode * period_node)
+{
+  if (period_node) {
+    g_free (period_node->id);
+    gst_mpdparser_free_seg_base_type_ext (period_node->SegmentBase);
+    gst_mpdparser_free_segment_list_node (period_node->SegmentList);
+    gst_mpdparser_free_segment_template_node (period_node->SegmentTemplate);
+    g_list_foreach (period_node->AdaptationSets,
+        (GFunc) gst_mpdparser_free_adaptation_set_node, NULL);
+    g_list_free (period_node->AdaptationSets);
+    g_list_foreach (period_node->Subsets,
+        (GFunc) gst_mpdparser_free_subset_node, NULL);
+    g_list_free (period_node->Subsets);
+    g_list_foreach (period_node->BaseURLs,
+        (GFunc) gst_mpdparser_free_base_url_node, NULL);
+    g_list_free (period_node->BaseURLs);
+    g_slice_free (GstPeriodNode, period_node);
+  }
+}
+
+static void
+gst_mpdparser_free_subset_node (GstSubsetNode * subset_node)
+{
+  if (subset_node) {
+    g_free (subset_node->contains);
+    g_slice_free (GstSubsetNode, subset_node);
+  }
+}
+
+static void
+gst_mpdparser_free_segment_template_node (GstSegmentTemplateNode *
+    segment_template_node)
+{
+  if (segment_template_node) {
+    g_free (segment_template_node->media);
+    g_free (segment_template_node->index);
+    g_free (segment_template_node->initialization);
+    g_free (segment_template_node->bitstreamSwitching);
+    /* MultipleSegmentBaseType extension */
+    gst_mpdparser_free_mult_seg_base_type_ext
+        (segment_template_node->MultSegBaseType);
+    g_slice_free (GstSegmentTemplateNode, segment_template_node);
+  }
+}
+
+static void
+gst_mpdparser_free_representation_base_type (GstRepresentationBaseType *
+    representation_base)
+{
+  if (representation_base) {
+    g_free (representation_base->profiles);
+    g_slice_free (GstRatio, representation_base->sar);
+    g_slice_free (GstFrameRate, representation_base->frameRate);
+    g_free (representation_base->audioSamplingRate);
+    g_free (representation_base->mimeType);
+    g_free (representation_base->segmentProfiles);
+    g_free (representation_base->codecs);
+    g_free (representation_base->scanType);
+    g_list_foreach (representation_base->FramePacking,
+        (GFunc) gst_mpdparser_free_descriptor_type_node, NULL);
+    g_list_free (representation_base->FramePacking);
+    g_list_foreach (representation_base->AudioChannelConfiguration,
+        (GFunc) gst_mpdparser_free_descriptor_type_node, NULL);
+    g_list_free (representation_base->AudioChannelConfiguration);
+    g_list_foreach (representation_base->ContentProtection,
+        (GFunc) gst_mpdparser_free_descriptor_type_node, NULL);
+    g_list_free (representation_base->ContentProtection);
+    g_slice_free (GstRepresentationBaseType, representation_base);
+  }
+}
+
+static void
+gst_mpdparser_free_adaptation_set_node (GstAdaptationSetNode *
+    adaptation_set_node)
+{
+  if (adaptation_set_node) {
+    g_free (adaptation_set_node->lang);
+    g_free (adaptation_set_node->contentType);
+    g_slice_free (GstRatio, adaptation_set_node->par);
+    g_slice_free (GstFrameRate, adaptation_set_node->minFrameRate);
+    g_slice_free (GstFrameRate, adaptation_set_node->maxFrameRate);
+    g_slice_free (GstConditionalUintType,
+        adaptation_set_node->segmentAlignment);
+    g_slice_free (GstConditionalUintType,
+        adaptation_set_node->subsegmentAlignment);
+    g_list_foreach (adaptation_set_node->Accessibility,
+        (GFunc) gst_mpdparser_free_descriptor_type_node, NULL);
+    g_list_free (adaptation_set_node->Accessibility);
+    g_list_foreach (adaptation_set_node->Role,
+        (GFunc) gst_mpdparser_free_descriptor_type_node, NULL);
+    g_list_free (adaptation_set_node->Role);
+    g_list_foreach (adaptation_set_node->Rating,
+        (GFunc) gst_mpdparser_free_descriptor_type_node, NULL);
+    g_list_free (adaptation_set_node->Rating);
+    g_list_foreach (adaptation_set_node->Viewpoint,
+        (GFunc) gst_mpdparser_free_descriptor_type_node, NULL);
+    g_list_free (adaptation_set_node->Viewpoint);
+    gst_mpdparser_free_representation_base_type
+        (adaptation_set_node->RepresentationBase);
+    gst_mpdparser_free_seg_base_type_ext (adaptation_set_node->SegmentBase);
+    gst_mpdparser_free_segment_list_node (adaptation_set_node->SegmentList);
+    gst_mpdparser_free_segment_template_node (adaptation_set_node->
+        SegmentTemplate);
+    g_list_foreach (adaptation_set_node->BaseURLs,
+        (GFunc) gst_mpdparser_free_base_url_node, NULL);
+    g_list_free (adaptation_set_node->BaseURLs);
+    g_list_foreach (adaptation_set_node->Representations,
+        (GFunc) gst_mpdparser_free_representation_node, NULL);
+    g_list_free (adaptation_set_node->Representations);
+    g_list_foreach (adaptation_set_node->ContentComponents,
+        (GFunc) gst_mpdparser_free_content_component_node, NULL);
+    g_list_free (adaptation_set_node->ContentComponents);
+    g_slice_free (GstAdaptationSetNode, adaptation_set_node);
+  }
+}
+
+static void
+gst_mpdparser_free_representation_node (GstRepresentationNode *
+    representation_node)
+{
+  if (representation_node) {
+    g_free (representation_node->id);
+    g_strfreev (representation_node->dependencyId);
+    g_strfreev (representation_node->mediaStreamStructureId);
+    gst_mpdparser_free_representation_base_type
+        (representation_node->RepresentationBase);
+    g_list_foreach (representation_node->SubRepresentations,
+        (GFunc) gst_mpdparser_free_subrepresentation_node, NULL);
+    g_list_free (representation_node->SubRepresentations);
+    gst_mpdparser_free_seg_base_type_ext (representation_node->SegmentBase);
+    gst_mpdparser_free_segment_template_node (representation_node->
+        SegmentTemplate);
+    gst_mpdparser_free_segment_list_node (representation_node->SegmentList);
+    g_list_foreach (representation_node->BaseURLs,
+        (GFunc) gst_mpdparser_free_base_url_node, NULL);
+    g_list_free (representation_node->BaseURLs);
+    g_slice_free (GstRepresentationNode, representation_node);
+  }
+}
+
+static void
+gst_mpdparser_free_subrepresentation_node (GstSubRepresentationNode *
+    subrep_node)
+{
+  if (subrep_node) {
+    gst_mpdparser_free_representation_base_type (subrep_node->
+        RepresentationBase);
+    g_free (subrep_node->dependencyLevel);
+    g_strfreev (subrep_node->contentComponent);
+  }
+}
+
+static void
+gst_mpdparser_free_s_node (GstSNode * s_node)
+{
+  if (s_node) {
+    g_slice_free (GstSNode, s_node);
+  }
+}
+
+static void
+gst_mpdparser_free_segment_timeline_node (GstSegmentTimelineNode * seg_timeline)
+{
+  if (seg_timeline) {
+    g_list_foreach (seg_timeline->S, (GFunc) gst_mpdparser_free_s_node, NULL);
+    g_list_free (seg_timeline->S);
+    g_slice_free (GstSegmentTimelineNode, seg_timeline);
+  }
+}
+
+static void
+gst_mpdparser_free_url_type_node (GstURLType * url_type_node)
+{
+  if (url_type_node) {
+    g_free (url_type_node->sourceURL);
+    g_slice_free (GstRange, url_type_node->range);
+    g_slice_free (GstURLType, url_type_node);
+  }
+}
+
+static void
+gst_mpdparser_free_seg_base_type_ext (GstSegmentBaseType * seg_base_type)
+{
+  if (seg_base_type) {
+    g_free (seg_base_type->indexRange);
+    gst_mpdparser_free_url_type_node (seg_base_type->Initialization);
+    gst_mpdparser_free_url_type_node (seg_base_type->RepresentationIndex);
+    g_slice_free (GstSegmentBaseType, seg_base_type);
+  }
+}
+
+static void
+gst_mpdparser_free_mult_seg_base_type_ext (GstMultSegmentBaseType *
+    mult_seg_base_type)
+{
+  if (mult_seg_base_type) {
+    /* SegmentBaseType extension */
+    gst_mpdparser_free_seg_base_type_ext (mult_seg_base_type->SegBaseType);
+    gst_mpdparser_free_segment_timeline_node
+        (mult_seg_base_type->SegmentTimeline);
+    gst_mpdparser_free_url_type_node (mult_seg_base_type->BitstreamSwitching);
+    g_slice_free (GstMultSegmentBaseType, mult_seg_base_type);
+  }
+}
+
+static void
+gst_mpdparser_free_segment_list_node (GstSegmentListNode * segment_list_node)
+{
+  if (segment_list_node) {
+    g_list_foreach (segment_list_node->SegmentURL,
+        (GFunc) gst_mpdparser_free_segment_url_node, NULL);
+    g_list_free (segment_list_node->SegmentURL);
+    /* MultipleSegmentBaseType extension */
+    gst_mpdparser_free_mult_seg_base_type_ext
+        (segment_list_node->MultSegBaseType);
+    g_slice_free (GstSegmentListNode, segment_list_node);
+  }
+}
+
+static void
+gst_mpdparser_free_segment_url_node (GstSegmentURLNode * segment_url)
+{
+  if (segment_url) {
+    g_free (segment_url->media);
+    g_slice_free (GstRange, segment_url->mediaRange);
+    g_free (segment_url->index);
+    g_slice_free (GstRange, segment_url->indexRange);
+    g_slice_free (GstSegmentURLNode, segment_url);
+  }
+}
+
+static void
+gst_mpdparser_free_base_url_node (GstBaseURL * base_url_node)
+{
+  if (base_url_node) {
+    g_free (base_url_node->baseURL);
+    g_free (base_url_node->serviceLocation);
+    g_free (base_url_node->byteRange);
+    g_slice_free (GstBaseURL, base_url_node);
+  }
+}
+
+static void
+gst_mpdparser_free_descriptor_type_node (GstDescriptorType * descriptor_type)
+{
+  if (descriptor_type) {
+    g_free (descriptor_type->schemeIdUri);
+    g_free (descriptor_type->value);
+  }
+}
+
+static void
+gst_mpdparser_free_content_component_node (GstContentComponentNode *
+    content_component_node)
+{
+  if (content_component_node) {
+    g_free (content_component_node->lang);
+    g_free (content_component_node->contentType);
+    g_slice_free (GstRatio, content_component_node->par);
+    g_list_foreach (content_component_node->Accessibility,
+        (GFunc) gst_mpdparser_free_descriptor_type_node, NULL);
+    g_list_free (content_component_node->Accessibility);
+    g_list_foreach (content_component_node->Role,
+        (GFunc) gst_mpdparser_free_descriptor_type_node, NULL);
+    g_list_free (content_component_node->Role);
+    g_list_foreach (content_component_node->Rating,
+        (GFunc) gst_mpdparser_free_descriptor_type_node, NULL);
+    g_list_free (content_component_node->Rating);
+    g_list_foreach (content_component_node->Viewpoint,
+        (GFunc) gst_mpdparser_free_descriptor_type_node, NULL);
+    g_list_free (content_component_node->Viewpoint);
+    g_slice_free (GstContentComponentNode, content_component_node);
+  }
+}
+
+static void
+gst_mpdparser_free_stream_period (GstStreamPeriod * stream_period)
+{
+  if (stream_period) {
+    g_slice_free (GstStreamPeriod, stream_period);
+  }
+}
+
+static void
+gst_mpdparser_free_media_segment (GstMediaSegment * media_segment)
+{
+  if (media_segment) {
+    g_slice_free (GstMediaSegment, media_segment);
+  }
+}
+
+static void
+gst_mpdparser_free_active_stream (GstActiveStream * active_stream)
+{
+  if (active_stream) {
+    g_list_foreach (active_stream->segments,
+        (GFunc) gst_mpdparser_free_media_segment, NULL);
+    if (active_stream->segments)
+      g_list_free (active_stream->segments);
+    g_slice_free (GstActiveStream, active_stream);
+  }
+}
+
+static gchar *
+gst_mpdparser_get_segmentURL_for_range (const gchar * url, GstRange * range)
+{
+  gchar *segmentURL;
+
+  if (range) {
+    gchar *range_suffix;
+    range_suffix =
+        g_strdup_printf ("?range=%llu-%llu", range->first_byte_pos,
+        range->last_byte_pos);
+    segmentURL = g_strconcat (url, range_suffix, NULL);
+    g_free (range_suffix);
+  } else {
+    segmentURL = g_strdup (url);
+  }
+
+  return segmentURL;
+}
+
+static gchar *
+gst_mpdparser_get_mediaURL (GstMpdClient * client,
+    GstSegmentURLNode * segmentURL)
+{
+  const gchar *url_prefix;
+
+  g_return_val_if_fail (client != NULL, NULL);
+  g_return_val_if_fail (segmentURL != NULL, NULL);
+
+  url_prefix =
+      segmentURL->media ? segmentURL->
+      media : gst_mpdparser_get_baseURL (client);
+  g_return_val_if_fail (url_prefix != NULL, NULL);
+
+  return gst_mpdparser_get_segmentURL_for_range (url_prefix,
+      segmentURL->mediaRange);//if not present @media attribute, it is mapped to baseURL
+}
+
+static gchar *
+gst_mpdparser_get_initializationURL (GstURLType * InitializationURL)
+{
+  g_return_val_if_fail (InitializationURL != NULL, NULL);
+  g_return_val_if_fail (InitializationURL->sourceURL != NULL, NULL);
+
+  return gst_mpdparser_get_segmentURL_for_range (InitializationURL->sourceURL,
+      InitializationURL->range);
+}
+
+static gchar *
+gst_mpdparser_build_URL_from_template (const gchar * url_template,
+    const gchar * id, guint number, guint bandwidth, guint time)
+{
+  static gchar default_format[] = "%01d";
+  gchar **tokens, *token, *ret, *format;
+  gint i, num_tokens;
+  gboolean last_token_par = TRUE;       /* last token was a parameter */
+
+  g_return_val_if_fail (url_template != NULL, NULL);
+  tokens = g_strsplit_set (url_template, "$", -1);
+  if (!tokens) {
+    GST_WARNING ("Scan of URL template failed!");
+    return NULL;
+  }
+  num_tokens = g_strv_length (tokens);
+
+  for (i = 0; i < num_tokens; i++) {
+    token = tokens[i];
+    format = default_format;
+
+    if (!g_strcmp0 (token, "RepresentationID")) {
+      tokens[i] = g_strdup_printf ("%s", id);
+      g_free (token);
+      last_token_par = TRUE;
+    } else if (!strncmp (token, "Number", 6)) {
+      if (strlen (token) > 6) {
+        format = token + 6;     /* format tag */
+      }
+      tokens[i] = g_strdup_printf (format, number);
+      g_free (token);
+      last_token_par = TRUE;
+    } else if (!strncmp (token, "Bandwidth", 9)) {
+      if (strlen (token) > 9) {
+        format = token + 9;     /* format tag */
+      }
+      tokens[i] = g_strdup_printf (format, bandwidth);
+      g_free (token);
+      last_token_par = TRUE;
+    } else if (!strncmp (token, "Time", 4)) {
+      if (strlen (token) > 4) {
+        format = token + 4;     /* format tag */
+      }
+      tokens[i] = g_strdup_printf (format, time);
+      g_free (token);
+      last_token_par = TRUE;
+    } else if (!g_strcmp0 (token, "")) {
+      if (!last_token_par) {
+        tokens[i] = g_strdup_printf ("%s", "$");
+        g_free (token);
+        last_token_par = TRUE;
+      }
+    } else {
+      last_token_par = FALSE;
+    }
+  }
+
+  ret = g_strjoinv (NULL, tokens);
+  g_strfreev (tokens);
+
+  return ret;
+}
+
+static GstStreamPeriod *
+gst_mpdparser_get_stream_period (GstMpdClient * client)
+{
+  g_return_val_if_fail (client != NULL, NULL);
+  g_return_val_if_fail (client->periods != NULL, NULL);
+
+  return g_list_nth_data (client->periods, client->period_idx);
+}
+
+/* select a stream and extract the baseURL (if present) */
+static gchar *
+gst_mpdparser_parse_baseURL (GstMpdClient * client)
+{
+  GstActiveStream *stream;
+  GstStreamPeriod *stream_period;
+  GstBaseURL *baseURL;
+  GList *list;
+  static gchar *baseURL_array[5];
+  static gchar empty[] = "";
+  gchar *ret = NULL;
+
+  stream =
+      gst_mpdparser_get_active_stream_by_index (client, client->stream_idx);
+  g_return_val_if_fail (stream != NULL, empty);
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, empty);
+  g_return_val_if_fail (stream_period->period != NULL, empty);
+
+  baseURL_array[0] = baseURL_array[1] = baseURL_array[2] = baseURL_array[3] =
+      empty;
+  baseURL_array[4] = NULL;
+
+  /* FIXME: this simple implementation is not fully compliant with RFC 3986 */
+  if ((list = client->mpd_node->BaseURLs) != NULL) {
+    baseURL = g_list_nth_data (list, stream->mpd_baseURL_idx);
+    if (!baseURL) {
+      baseURL = list->data;
+    }
+    baseURL_array[0] = baseURL->baseURL;
+  }
+  if ((list = stream_period->period->BaseURLs) != NULL) {
+    baseURL = g_list_nth_data (list, stream->period_baseURL_idx);
+    if (!baseURL) {
+      baseURL = list->data;
+    }
+    baseURL_array[1] = baseURL->baseURL;
+  }
+  if ((list = stream->cur_adapt_set->BaseURLs) != NULL) {
+    baseURL = g_list_nth_data (list, stream->adaptset_baseURL_idx);
+    if (!baseURL) {
+      baseURL = list->data;
+    }
+    baseURL_array[2] = baseURL->baseURL;
+  }
+  if ((list = stream->cur_representation->BaseURLs) != NULL) {
+    baseURL = g_list_nth_data (list, stream->repr_baseURL_idx);
+    if (!baseURL) {
+      baseURL = list->data;
+    }
+    baseURL_array[3] = baseURL->baseURL;
+  }
+
+  ret = g_strjoinv (NULL, baseURL_array);
+  /* get base URI from MPD file URI, if the "http" scheme is missing */
+  if (client->mpd_uri != NULL && strncmp (ret, "http://", 7) != 0) {
+    gchar *last_sep, *tmp1, *tmp2;
+    last_sep = strrchr (client->mpd_uri, '/');
+    if (last_sep) {
+      tmp1 = g_strndup (client->mpd_uri, last_sep - client->mpd_uri + 1);
+      tmp2 = ret;
+      GST_DEBUG ("Got base URI from MPD file URI %s", tmp1);
+      ret = g_strconcat (tmp1, tmp2, NULL);
+      g_free (tmp1);
+      g_free (tmp2);
+    }
+  }
+
+  return ret;
+}
+
+static GstClockTime
+gst_mpd_client_get_segment_duration (GstMpdClient * client, GstActiveStream *stream)
+{
+  GstStreamPeriod *stream_period;
+  GstMultSegmentBaseType *base = NULL;
+  GstClockTime duration;
+  guint timescale;
+
+  g_return_val_if_fail (stream != NULL, GST_CLOCK_TIME_NONE);
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, GST_CLOCK_TIME_NONE);
+
+  if (stream->cur_segment_list) {
+    base = stream->cur_segment_list->MultSegBaseType;
+  } else if (stream->cur_seg_template) {
+    base = stream->cur_seg_template->MultSegBaseType;
+  }
+
+  if (base == NULL || base->SegBaseType == NULL) {
+    /* this may happen when we have a single segment */
+    duration = stream_period->duration;
+  } else {
+    duration = base->duration * GST_SECOND;
+    timescale = base->SegBaseType->timescale;
+
+    if (timescale > 1)
+      duration /= timescale;
+  }
+
+  return duration;
+}
+
+/*****************************/
+/******* API functions *******/
+/*****************************/
+
+GstMpdClient *
+gst_mpd_client_new ()
+{
+  GstMpdClient *client;
+
+  client = g_new0 (GstMpdClient, 1);
+  client->lock = g_mutex_new ();
+
+  client->download_failed_count = 0;
+
+  return client;
+}
+
+void
+gst_active_streams_free (GstMpdClient * client)
+{
+  if (client->active_streams) {
+    g_list_foreach (client->active_streams,
+        (GFunc) gst_mpdparser_free_active_stream, NULL);
+    g_list_free (client->active_streams);
+    client->active_streams = NULL;
+  }
+}
+
+void
+gst_mpd_client_free (GstMpdClient * client)
+{
+  g_return_if_fail (client != NULL);
+
+  if (client->mpd_node)
+    gst_mpdparser_free_mpd_node (client->mpd_node);
+
+  if (client->periods) {
+    g_list_foreach (client->periods,
+        (GFunc) gst_mpdparser_free_stream_period, NULL);
+    g_list_free (client->periods);
+  }
+
+  gst_active_streams_free (client);
+
+  if (client->lock)
+    g_mutex_free (client->lock);
+
+  g_free (client->mpd_uri);
+
+  g_free (client);
+}
+
+gboolean
+gst_mpd_parse (GstMpdClient * client, const gchar * data, gint size)
+{
+  if (data) {
+    xmlDocPtr doc;
+    xmlNode *root_element = NULL;
+
+    GST_DEBUG ("MPD file fully buffered, start parsing...");
+
+    GST_MPD_CLIENT_LOCK (client);
+    /* parse the complete MPD file into a tree (using the libxml2 default parser API) */
+
+    /* this initialize the library and check potential ABI mismatches
+     * between the version it was compiled for and the actual shared
+     * library used
+     */
+    LIBXML_TEST_VERSION
+        /* parse "data" into a document (which is a libxml2 tree structure xmlDoc) */
+        doc = xmlReadMemory (data, size, "noname.xml", NULL, 0);
+    if (doc == NULL) {
+      GST_ERROR ("failed to parse the MPD file");
+      GST_MPD_CLIENT_UNLOCK (client);
+      return FALSE;
+    } else {
+      /* get the root element node */
+      root_element = xmlDocGetRootElement (doc);
+
+      if (root_element->type != XML_ELEMENT_NODE
+          || xmlStrcmp (root_element->name, (xmlChar *) "MPD") != 0) {
+        GST_ERROR
+            ("can not find the root element MPD, failed to parse the MPD file");
+      } else {
+        /* now we can parse the MPD root node and all children nodes, recursively */
+        gst_mpdparser_parse_root_node (&client->mpd_node, root_element);
+      }
+      /* free the document */
+      xmlFreeDoc (doc);
+      /* dump XML library memory for debugging */
+      xmlMemoryDump ();
+    }
+    GST_MPD_CLIENT_UNLOCK (client);
+
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+const gchar *
+gst_mpdparser_get_baseURL (GstMpdClient * client)
+{
+  GstActiveStream *stream;
+
+  g_return_val_if_fail (client != NULL, NULL);
+  g_return_val_if_fail (client->active_streams != NULL, NULL);
+  stream = g_list_nth_data (client->active_streams, client->stream_idx);
+  g_return_val_if_fail (stream != NULL, NULL);
+
+  return stream->baseURL;
+}
+
+gboolean
+gst_mpdparser_get_chunk_by_index (GstMpdClient * client, guint indexStream,
+    guint indexChunk, GstMediaSegment *segment)
+{
+  GstActiveStream *stream;
+
+  /* select stream */
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (segment != NULL, FALSE);
+  g_return_val_if_fail (client->active_streams != NULL, FALSE);
+  stream = g_list_nth_data (client->active_streams, indexStream);
+  g_return_val_if_fail (stream != NULL, FALSE);
+
+  if(stream->segments) {
+    GstMediaSegment *list_segment;
+    if ( indexChunk >= g_list_length (stream->segments))
+      return FALSE;
+    list_segment = g_list_nth_data (stream->segments, indexChunk);
+    memcpy (segment, list_segment, sizeof (GstMediaSegment));
+  } else {
+    GstClockTime duration;
+    GstStreamPeriod *stream_period;
+    GstClockTime start_time;
+    stream_period = gst_mpdparser_get_stream_period (client);
+    g_return_val_if_fail (stream->cur_seg_template->MultSegBaseType->SegmentTimeline == NULL, FALSE);
+    g_return_val_if_fail (stream_period != NULL, FALSE);
+    g_return_val_if_fail (stream_period->period != NULL, FALSE);
+
+    duration = gst_mpd_client_get_segment_duration (client, stream);
+    if (!GST_CLOCK_TIME_IS_VALID (duration))
+      return FALSE;
+
+    start_time = duration * indexChunk;
+    if (GST_CLOCK_TIME_IS_VALID (stream_period->start) && GST_CLOCK_TIME_IS_VALID (stream_period->duration)
+      && start_time >= stream_period->start + stream_period->duration)
+      return FALSE;
+
+    segment->number = indexChunk + stream->cur_seg_template->MultSegBaseType->startNumber;
+    segment->start_time = start_time;
+    segment->duration = duration;
+    segment->SegmentURL = NULL;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_mpd_client_add_media_segment (GstActiveStream * stream,
+    GstSegmentURLNode * url_node, guint number, guint start,
+    GstClockTime start_time, GstClockTime duration)
+{
+  GstMediaSegment *media_segment;
+
+  media_segment = g_slice_new0 (GstMediaSegment);
+  if (media_segment == NULL) {
+    GST_WARNING ("Allocation of GstMediaSegment struct failed!");
+    return FALSE;
+  }
+  stream->segments = g_list_append (stream->segments, media_segment);
+  media_segment->SegmentURL = url_node;
+  media_segment->number = number;
+  media_segment->start = start;
+  media_segment->start_time = start_time;
+  media_segment->duration = duration;
+
+  return TRUE;
+}
+
+gboolean
+gst_mpd_client_setup_representation (GstMpdClient * client,
+    GstActiveStream * stream, GstRepresentationNode * representation)
+{
+  GstStreamPeriod *stream_period;
+  GList *rep_list;
+  GstClockTime PeriodStart, PeriodEnd, start_time, duration;
+  GstMediaSegment *last_media_segment;
+  guint i, start;
+
+  if (stream->cur_adapt_set == NULL) {
+    GST_WARNING ("No valid AdaptationSet node in the MPD file, aborting...");
+    return FALSE;
+  }
+
+  rep_list = stream->cur_adapt_set->Representations;
+  stream->cur_representation = representation;
+  stream->representation_idx = g_list_index (rep_list, representation);
+
+  /* clean the old segment list, if any */
+  if (stream->segments) {
+    g_list_foreach (stream->segments,
+        (GFunc) gst_mpdparser_free_media_segment, NULL);
+    g_list_free (stream->segments);
+    stream->segments = NULL;
+  }
+
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, FALSE);
+  g_return_val_if_fail (stream_period->period != NULL, FALSE);
+
+  PeriodStart = stream_period->start;
+  if (GST_CLOCK_TIME_IS_VALID (stream_period->duration))
+    PeriodEnd = stream_period->start + stream_period->duration;
+  else
+    PeriodEnd = GST_CLOCK_TIME_NONE;
+
+  GST_LOG ("Building segment list for Period from %" GST_TIME_FORMAT " to %"
+      GST_TIME_FORMAT, GST_TIME_ARGS (PeriodStart), GST_TIME_ARGS (PeriodEnd));
+
+  if (representation->SegmentBase != NULL
+      || representation->SegmentList != NULL) {
+    GList *SegmentURL;
+
+    /* get the first segment_base of the selected representation */
+    if ((stream->cur_segment_base =
+            gst_mpdparser_get_segment_base (stream_period->period,
+                stream->cur_adapt_set, representation)) == NULL) {
+      GST_DEBUG ("No useful SegmentBase node for the current Representation");
+    }
+
+    /* get the first segment_list of the selected representation */
+    if ((stream->cur_segment_list =
+            gst_mpdparser_get_segment_list (stream_period->period,
+                stream->cur_adapt_set, representation)) == NULL) {
+      GST_DEBUG ("No useful SegmentList node for the current Representation");
+      /* here we should have a single segment for each representation, whose URL is encoded in the baseURL element */
+      if (!gst_mpd_client_add_media_segment (stream, NULL, 1, 0, PeriodStart,
+              PeriodEnd)) {
+        return FALSE;
+      }
+    } else {
+      /* build the list of GstMediaSegment nodes from the SegmentList node */
+      SegmentURL = stream->cur_segment_list->SegmentURL;
+      if (SegmentURL == NULL) {
+        GST_WARNING
+            ("No valid list of SegmentURL nodes in the MPD file, aborting...");
+        return FALSE;
+      }
+
+      /* build segment list */
+      i = stream->cur_segment_list->MultSegBaseType->startNumber;
+      start = 0;
+      start_time = PeriodStart;
+
+      GST_LOG ("Building media segment list using a SegmentList node");
+      if (stream->cur_segment_list->MultSegBaseType->SegmentTimeline) {
+        GstSegmentTimelineNode *timeline;
+        GstSNode *S;
+        GList *list;
+
+        timeline = stream->cur_segment_list->MultSegBaseType->SegmentTimeline;
+        for (list = g_list_first (timeline->S); list; list = g_list_next (list)) {
+          guint j, timescale;
+
+          S = (GstSNode *) list->data;
+          GST_LOG ("Processing S node: d=%d r=%d t=%d", S->d, S->r, S->t);
+          duration = S->d * GST_SECOND;
+          timescale =
+              stream->cur_segment_list->MultSegBaseType->SegBaseType->timescale;
+          if (timescale > 1)
+            duration /= timescale;
+          if (S->t > 0) {
+            start = S->t;
+            start_time = S->t * GST_SECOND;
+            if (timescale > 1)
+              start_time /= timescale;
+          }
+
+          for (j = 0; j <= S->r && SegmentURL != NULL; j++) {
+            if (!gst_mpd_client_add_media_segment (stream, SegmentURL->data, i,
+                    start, start_time, duration)) {
+              return FALSE;
+            }
+            i++;
+            start += S->d;
+            start_time += duration;
+            SegmentURL = g_list_next (SegmentURL);
+          }
+        }
+      } else {
+        duration =gst_mpd_client_get_segment_duration (client, stream);
+        if (!GST_CLOCK_TIME_IS_VALID (duration))
+          return FALSE;
+
+        while (SegmentURL) {
+          if (!gst_mpd_client_add_media_segment (stream, SegmentURL->data, i, 0,
+                  start_time, duration)) {
+            return FALSE;
+          }
+          i++;
+          start_time += duration;
+          SegmentURL = g_list_next (SegmentURL);
+        }
+      }
+    }
+  } else {
+    if (representation->SegmentTemplate != NULL) {
+      stream->cur_seg_template = representation->SegmentTemplate;
+    } else if (stream->cur_adapt_set->SegmentTemplate != NULL) {
+      stream->cur_seg_template = stream->cur_adapt_set->SegmentTemplate;
+    } else if (stream_period->period->SegmentTemplate != NULL) {
+      stream->cur_seg_template = stream_period->period->SegmentTemplate;
+    }
+
+    if (stream->cur_seg_template == NULL
+        || stream->cur_seg_template->MultSegBaseType == NULL) {
+      /* here we should have a single segment for each representation, whose URL is encoded in the baseURL element */
+      if (!gst_mpd_client_add_media_segment (stream, NULL, 1, 0, 0, PeriodEnd)) {
+        return FALSE;
+      }
+    } else {
+      /* build segment list */
+      i = stream->cur_seg_template->MultSegBaseType->startNumber;
+      start = 0;
+      start_time = PeriodStart;
+
+      GST_LOG ("Building media segment list using this template: %s",
+          stream->cur_seg_template->media);
+      if (stream->cur_seg_template->MultSegBaseType->SegmentTimeline) {
+        GstSegmentTimelineNode *timeline;
+        GstSNode *S;
+        GList *list;
+
+        timeline = stream->cur_seg_template->MultSegBaseType->SegmentTimeline;
+        for (list = g_list_first (timeline->S); list; list = g_list_next (list)) {
+          guint j, timescale;
+
+          S = (GstSNode *) list->data;
+          GST_LOG ("Processing S node: d=%d r=%d t=%d", S->d, S->r, S->t);
+          duration = S->d * GST_SECOND;
+          timescale =
+              stream->cur_seg_template->MultSegBaseType->SegBaseType->timescale;
+          if (timescale > 1)
+            duration /= timescale;
+          if (S->t > 0) {
+            start = S->t;
+            start_time = S->t * GST_SECOND;
+            if (timescale > 1)
+              start_time /= timescale;
+          }
+
+          for (j = 0; j <= S->r; j++) {
+            if (!gst_mpd_client_add_media_segment (stream, NULL, i, start,
+                    start_time, duration)) {
+              return FALSE;
+            }
+            i++;
+            start += S->d;
+            start_time += duration;
+          }
+        }
+      } else {
+         /*The segment is created on demand with the template, no need to build a list */
+      }
+    }
+  }
+
+  /* check duration of last segment */
+  if(stream->segments)
+    last_media_segment = g_list_last (stream->segments)->data;
+  else
+    last_media_segment = NULL;
+  if (last_media_segment && GST_CLOCK_TIME_IS_VALID (PeriodEnd)) {
+    if (last_media_segment->start_time + last_media_segment->duration >
+        PeriodEnd) {
+      last_media_segment->duration = PeriodEnd - last_media_segment->start_time;
+      GST_LOG ("Fixed duration of last segment: %" GST_TIME_FORMAT,
+          GST_TIME_ARGS (last_media_segment->duration));
+    }
+    GST_LOG ("Built a list of %d segments", last_media_segment->number);
+  }
+
+  g_free (stream->baseURL);
+  stream->baseURL = gst_mpdparser_parse_baseURL (client);
+
+  return TRUE;
+}
+
+gboolean
+gst_mpd_client_setup_media_presentation (GstMpdClient * client)
+{
+  GstStreamPeriod *stream_period;
+  GstPeriodNode *period_node;
+  GstClockTime start, duration;
+  GList *list, *next;
+  guint idx;
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (client->mpd_node != NULL, FALSE);
+
+  GST_DEBUG ("Building the list of Periods in the Media Presentation");
+  GST_MPD_CLIENT_LOCK (client);
+  /* clean the old period list, if any */
+  if (client->periods) {
+    g_list_foreach (client->periods,
+        (GFunc) gst_mpdparser_free_stream_period, NULL);
+    g_list_free (client->periods);
+    client->periods = NULL;
+  }
+
+  idx = 0;
+  start = 0;
+  duration = GST_CLOCK_TIME_NONE;
+  for (list = g_list_first (client->mpd_node->Periods); list;
+      list = g_list_next (list)) {
+    period_node = (GstPeriodNode *) list->data;
+    if (period_node->start != -1) {
+      /* we have a regular period */
+      start = period_node->start * GST_MSECOND;
+    } else if (duration != GST_CLOCK_TIME_NONE) {
+      /* start time inferred from previous period, this is still a regular period */
+      start += duration;
+    } else if (idx == 0 && client->mpd_node->type == GST_MPD_FILE_TYPE_STATIC) {
+      /* first period of a static MPD file, start time is 0 */
+      start = 0;
+    } else if (gst_mpd_client_is_live (client)) {
+      /*it should be a live stream, let this pass.*/
+    } else {
+      /* this is an 'Early Available Period' */
+      goto early;
+    }
+
+    if (period_node->duration != -1) {
+      duration = period_node->duration * GST_MSECOND;
+    } else if ((next = g_list_next (list)) != NULL) {
+      /* try to infer this period duration from the start time of the next period */
+      GstPeriodNode *next_period_node = next->data;
+      if (next_period_node->start != -1) {
+        duration = next_period_node->start * GST_MSECOND - start;
+      } else {
+        /* Invalid MPD file! */
+        goto syntax_error;
+      }
+    } else if (client->mpd_node->mediaPresentationDuration != -1) {
+      /* last Period of the Media Presentation */
+      duration =
+          client->mpd_node->mediaPresentationDuration * GST_MSECOND - start;
+    } else if (gst_mpd_client_is_live (client)) {
+      /*it should be a live stream, let this pass.*/
+    } else {
+      /* Invalid MPD file! */
+      goto syntax_error;
+    }
+
+    stream_period = g_slice_new0 (GstStreamPeriod);
+    if (stream_period == NULL) {
+      goto no_mem;
+    }
+    client->periods = g_list_append (client->periods, stream_period);
+    stream_period->period = period_node;
+    stream_period->number = idx++;
+    stream_period->start = start;
+    stream_period->duration = duration;
+    ret = TRUE;
+    GST_LOG (" - added Period %d start=%" GST_TIME_FORMAT " duration=%"
+        GST_TIME_FORMAT, idx, GST_TIME_ARGS (start), GST_TIME_ARGS (duration));
+  }
+
+  GST_MPD_CLIENT_UNLOCK (client);
+  GST_DEBUG ("Found a total of %d valid Periods in the Media Presentation",
+      idx);
+  return ret;
+
+early:
+  GST_MPD_CLIENT_UNLOCK (client);
+  GST_WARNING
+      ("Found an Early Available Period, skipping the rest of the Media Presentation");
+  return ret;
+
+syntax_error:
+  GST_MPD_CLIENT_UNLOCK (client);
+  GST_WARNING
+      ("Cannot get the duration of the Period %d, skipping the rest of the Media Presentation",
+      idx);
+  return ret;
+
+no_mem:
+  GST_MPD_CLIENT_UNLOCK (client);
+  GST_WARNING ("Allocation of GstStreamPeriod struct failed!");
+  return FALSE;
+}
+
+gboolean
+gst_mpd_client_setup_streaming (GstMpdClient * client,
+    GstStreamMimeType mimeType, gchar * lang)
+{
+  GstActiveStream *stream;
+  GstStreamPeriod *stream_period;
+  GstAdaptationSetNode *adapt_set;
+  GstRepresentationNode *representation;
+  GList *rep_list = NULL;
+
+  stream_period = gst_mpdparser_get_stream_period (client);
+  if (stream_period == NULL || stream_period->period == NULL) {
+    GST_DEBUG ("No more Period nodes in the MPD file, terminating...");
+    return FALSE;
+  }
+
+  switch (mimeType) {
+    case GST_STREAM_VIDEO:
+      /* select the adaptation set for the video pipeline */
+      adapt_set =
+          gst_mpdparser_get_adapt_set_with_mimeType_and_idx (stream_period->
+          period->AdaptationSets, "video", 0);
+      if (!adapt_set) {
+        GST_INFO ("No video adaptation set found");
+        return FALSE;
+      }
+      /* retrive the list of representations */
+      rep_list = adapt_set->Representations;
+      if (!rep_list) {
+        GST_WARNING ("Can not retrieve any representation, aborting...");
+        return FALSE;
+      }
+      break;
+    case GST_STREAM_AUDIO:
+      adapt_set =
+          gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang
+          (stream_period->period->AdaptationSets, "audio", lang);
+      /* if we did not found the requested audio language, get the first one */
+      if (!adapt_set)
+        adapt_set =
+            gst_mpdparser_get_first_adapt_set_with_mimeType (stream_period->
+            period->AdaptationSets, "audio");
+      if (!adapt_set) {
+        GST_INFO ("No audio adaptation set found");
+        return FALSE;
+      }
+      rep_list = adapt_set->Representations;
+      if (!rep_list) {
+        GST_WARNING ("Can not retrieve any representation, aborting...");
+        return FALSE;
+      }
+      break;
+    case GST_STREAM_APPLICATION:
+      adapt_set =
+          gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang
+          (stream_period->period->AdaptationSets, "application", lang);
+      /* if we did not found the requested subtitles language, get the first one */
+      if (!adapt_set)
+        adapt_set =
+            gst_mpdparser_get_first_adapt_set_with_mimeType (stream_period->
+            period->AdaptationSets, "application");
+      if (!adapt_set) {
+        GST_INFO ("No application adaptation set found");
+        return FALSE;
+      }
+      rep_list = adapt_set->Representations;
+      if (!rep_list) {
+        GST_WARNING ("Can not retrieve any representation, aborting...");
+        return FALSE;
+      }
+      break;
+    default:
+      GST_WARNING ("Unsupported mimeType %d", mimeType);
+      return FALSE;
+  }
+
+  stream = g_slice_new0 (GstActiveStream);
+  if (stream == NULL) {
+    GST_WARNING ("Allocation of active stream struct failed!");
+    return FALSE;
+  }
+  client->active_streams = g_list_append (client->active_streams, stream);
+
+  stream->mpd_baseURL_idx = 0;
+  stream->period_baseURL_idx = 0;
+  stream->adaptset_baseURL_idx = 0;
+  stream->repr_baseURL_idx = 0;
+
+  stream->mimeType = mimeType;
+  stream->cur_adapt_set = adapt_set;
+
+  /* retrive representation list */
+  if (stream->cur_adapt_set != NULL)
+    rep_list = stream->cur_adapt_set->Representations;
+#if 0
+  /* fast start */
+  representation =
+      gst_mpdparser_get_representation_with_max_bandwidth (rep_list,
+      stream->max_bandwidth);
+
+  if (!representation) {
+    GST_WARNING
+        ("Can not retrieve a representation with the requested bandwidth");
+    representation = gst_mpdparser_get_lowest_representation (rep_list);
+  }
+#else
+  /* slow start */
+  representation = gst_mpdparser_get_lowest_representation (rep_list);
+#endif
+
+  if (!representation) {
+    GST_WARNING ("No valid representation in the MPD file, aborting...");
+    return FALSE;
+  }
+
+  if (!gst_mpd_client_setup_representation (client, stream, representation))
+    return FALSE;
+
+  GST_INFO ("Successfully setup the download pipeline for mimeType %d",
+      mimeType);
+
+  return TRUE;
+}
+
+gboolean
+gst_mpd_client_get_next_fragment_timestamp (GstMpdClient * client,
+    guint stream_idx, GstClockTime * ts)
+{
+  GstActiveStream *stream;
+  gint segment_idx;
+  GstMediaSegment currentChunk;
+
+  GST_DEBUG ("Stream index: %i", stream_idx);
+  stream = g_list_nth_data (client->active_streams, stream_idx);
+  g_return_val_if_fail (stream != NULL, 0);
+
+  GST_MPD_CLIENT_LOCK (client);
+  segment_idx = gst_mpd_client_get_segment_index (stream);
+  GST_DEBUG ("Looking for fragment sequence chunk %d", segment_idx);
+
+
+  if (!gst_mpdparser_get_chunk_by_index (client, stream_idx, segment_idx, &currentChunk)) {
+    GST_MPD_CLIENT_UNLOCK (client);
+    return FALSE;
+  }
+
+  *ts = currentChunk.start_time;
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  return TRUE;
+}
+
+gboolean
+gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client,
+    guint stream_idx, GstClockTime * ts)
+{
+  GstActiveStream *stream;
+  gint segment_idx = 0;
+  GstMediaSegment currentChunk;
+
+  GST_DEBUG ("Stream index: %i", stream_idx);
+  stream = g_list_nth_data (client->active_streams, stream_idx);
+  g_return_val_if_fail (stream != NULL, 0);
+
+  GST_MPD_CLIENT_LOCK (client);
+  if (stream->segments)
+    segment_idx = g_list_length (stream->segments) - 1;
+  GST_DEBUG ("Looking for fragment sequence chunk %d", segment_idx);
+
+  if (!gst_mpdparser_get_chunk_by_index (client, stream_idx, segment_idx,
+          &currentChunk)) {
+    GST_MPD_CLIENT_UNLOCK (client);
+    return FALSE;
+  }
+
+  *ts = currentChunk.start_time;
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  return TRUE;
+}
+
+gboolean
+gst_mpd_client_get_next_fragment (GstMpdClient * client,
+    guint indexStream, gboolean * discontinuity, gchar ** uri,
+    GstClockTime * duration, GstClockTime * timestamp)
+{
+  GstActiveStream *stream = NULL;
+  GstMediaSegment currentChunk;
+  gchar *mediaURL = NULL;
+  guint segment_idx;
+
+  /* select stream */
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (client->active_streams != NULL, FALSE);
+  stream = g_list_nth_data (client->active_streams, indexStream);
+  g_return_val_if_fail (stream != NULL, FALSE);
+  g_return_val_if_fail (stream->cur_representation != NULL, FALSE);
+  g_return_val_if_fail (discontinuity != NULL, FALSE);
+
+  GST_MPD_CLIENT_LOCK (client);
+  segment_idx = gst_mpd_client_get_segment_index (stream);
+  GST_DEBUG ("Looking for fragment sequence chunk %d", segment_idx);
+
+  if (!gst_mpdparser_get_chunk_by_index (client, indexStream, segment_idx, &currentChunk)) {
+    GST_MPD_CLIENT_UNLOCK (client);
+    return FALSE;
+  }
+
+  if (currentChunk.SegmentURL != NULL) {
+    mediaURL = gst_mpdparser_get_mediaURL (client, currentChunk.SegmentURL);
+  } else if (stream->cur_seg_template != NULL) {
+    mediaURL =
+        gst_mpdparser_build_URL_from_template (stream->cur_seg_template->media,
+        stream->cur_representation->id, currentChunk.number,
+        stream->cur_representation->bandwidth, currentChunk.start);
+  }
+
+  *timestamp = currentChunk.start_time;
+  *duration = currentChunk.duration;
+  *discontinuity = segment_idx != currentChunk.number;
+  if (mediaURL == NULL) {
+    /* single segment with URL encoded in the baseURL syntax element */
+    *uri = g_strdup (gst_mpdparser_get_baseURL (client));
+  } else if (strncmp (mediaURL, "http://", 7) != 0) {
+    *uri = g_strconcat (gst_mpdparser_get_baseURL (client), mediaURL, NULL);
+    g_free (mediaURL);
+  } else {
+    *uri = mediaURL;
+  }
+  gst_mpd_client_set_segment_index (stream, segment_idx + 1);
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  GST_DEBUG ("Loading chunk with URL %s", *uri);
+
+  return TRUE;
+}
+
+gboolean
+gst_mpd_client_get_next_header (GstMpdClient * client, const gchar ** uri,
+    guint stream_idx)
+{
+  GstActiveStream *stream;
+  GstStreamPeriod *stream_period;
+
+  stream = gst_mpdparser_get_active_stream_by_index (client, stream_idx);
+  g_return_val_if_fail (stream != NULL, FALSE);
+  g_return_val_if_fail (stream->cur_representation != NULL, FALSE);
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, FALSE);
+  g_return_val_if_fail (stream_period->period != NULL, FALSE);
+
+  GST_DEBUG ("Looking for current representation header");
+  GST_MPD_CLIENT_LOCK (client);
+  *uri = NULL;
+  if (stream->cur_segment_base && stream->cur_segment_base->Initialization) {
+
+    if (stream->cur_segment_base->Initialization->sourceURL == NULL) {
+      stream->cur_segment_base->Initialization->sourceURL = gst_mpdparser_get_baseURL (client);
+    }//if not present initialization @sourceURL attribute, it's mapped to baseURL
+
+    *uri =
+        gst_mpdparser_get_initializationURL (stream->cur_segment_base->
+        Initialization);
+  } else if (stream->cur_seg_template) {
+    const gchar *initialization = NULL;
+    if (stream->cur_seg_template->initialization) {
+      initialization = stream->cur_seg_template->initialization;
+    } else if (stream->cur_adapt_set->SegmentTemplate
+        && stream->cur_adapt_set->SegmentTemplate->initialization) {
+      initialization = stream->cur_adapt_set->SegmentTemplate->initialization;
+    } else if (stream_period->period->SegmentTemplate
+        && stream_period->period->SegmentTemplate->initialization) {
+      initialization = stream_period->period->SegmentTemplate->initialization;
+    }
+    *uri = gst_mpdparser_build_URL_from_template (initialization,
+        stream->cur_representation->id, 0,
+        stream->cur_representation->bandwidth, 0);
+  }
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  return *uri == NULL ? FALSE : TRUE;
+}
+
+gboolean
+gst_mpd_client_get_stream_current_position (GstMpdClient * client, guint stream_idx, GstClockTime *ts)
+{
+  GstActiveStream *stream;
+  GstMediaSegment media_segment;
+  stream = gst_mpdparser_get_active_stream_by_index( client, stream_idx);
+  g_return_val_if_fail (stream != NULL, FALSE);
+  if(!gst_mpdparser_get_chunk_by_index(client, stream_idx,
+               gst_mpd_client_get_segment_index (stream), &media_segment))
+  {
+   return FALSE;
+  }
+
+  if (GST_CLOCK_TIME_IS_VALID (media_segment.start_time)) {
+  *ts = media_segment.start_time;
+   return TRUE;
+  } else {
+   return FALSE;
+  }
+}
+
+GstClockTime
+gst_mpd_client_get_next_fragment_duration (GstMpdClient * client)
+{
+  GstActiveStream *stream;
+  GstMediaSegment *media_segment;
+  gint seg_idx;
+
+  stream = g_list_nth_data (client->active_streams, client->stream_idx);
+  g_return_val_if_fail (stream != NULL, 0);
+  seg_idx = gst_mpd_client_get_segment_index (stream);
+
+  if(stream->segments) {
+    media_segment =
+        g_list_nth_data (stream->segments, seg_idx);
+    return media_segment == NULL ? 0 : media_segment->duration;
+  } else {
+    GstClockTime duration =
+        gst_mpd_client_get_segment_duration (client, stream);
+    g_return_val_if_fail (stream->cur_seg_template->MultSegBaseType->
+        SegmentTimeline == NULL, 0);
+
+    if (GST_CLOCK_TIME_IS_VALID (duration))
+      return duration;
+    return 0;
+  }
+}
+
+GstClockTime
+gst_mpd_client_get_media_presentation_duration (GstMpdClient * client)
+{
+  GstClockTime duration;
+
+  g_return_val_if_fail (client != NULL, GST_CLOCK_TIME_NONE);
+
+  GST_MPD_CLIENT_LOCK (client);
+  if (client->mpd_node->mediaPresentationDuration != -1) {
+    duration = client->mpd_node->mediaPresentationDuration * GST_MSECOND;
+  } else {
+    /* We can only get the duration for on-demand streams */
+    duration = GST_CLOCK_TIME_NONE;
+  }
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  return duration;
+}
+
+gboolean
+gst_mpd_client_set_period_index (GstMpdClient * client, guint period_idx)
+{
+  GstStreamPeriod *next_stream_period;
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (client->periods != NULL, FALSE);
+
+  GST_MPD_CLIENT_LOCK (client);
+  next_stream_period = g_list_nth_data (client->periods, period_idx);
+  if (next_stream_period != NULL) {
+    client->period_idx = period_idx;
+    ret = TRUE;
+  }
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  return ret;
+}
+
+guint
+gst_mpd_client_get_period_index (GstMpdClient * client)
+{
+  guint period_idx;
+
+  g_return_val_if_fail (client != NULL, 0);
+  GST_MPD_CLIENT_LOCK (client);
+  period_idx = client->period_idx;
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  return period_idx;
+}
+
+gboolean
+gst_mpd_client_set_period_id (GstMpdClient * client, const gchar * period_id)
+{
+  GstStreamPeriod *next_stream_period;
+  gboolean ret = FALSE;
+  GList *iter;
+  gint index = 0;
+
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (client->periods != NULL, FALSE);
+  g_return_val_if_fail (period_id != NULL, FALSE);
+
+  GST_MPD_CLIENT_LOCK (client);
+  for (iter = client->periods; iter; iter = g_list_next (iter)) {
+    next_stream_period = iter->data;
+
+    if (next_stream_period->period->id
+        && strcmp (next_stream_period->period->id, period_id) == 0) {
+      client->period_idx = index;
+      ret = TRUE;
+      break;
+    }
+    index++;
+  }
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  return ret;
+}
+
+const gchar *
+gst_mpd_client_get_period_id (GstMpdClient * client)
+{
+  GstStreamPeriod *period;
+  gchar *period_id = NULL;
+
+  g_return_val_if_fail (client != NULL, 0);
+  GST_MPD_CLIENT_LOCK (client);
+  period = g_list_nth_data (client->periods, client->period_idx);
+  if (period && period->period)
+    period_id = period->period->id;
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  return period_id;
+}
+
+gboolean
+gst_mpd_client_has_next_period (GstMpdClient * client)
+{
+  GList *next_stream_period;
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (client->periods != NULL, FALSE);
+
+  GST_MPD_CLIENT_LOCK (client);
+  next_stream_period =
+      g_list_nth_data (client->periods, client->period_idx + 1);
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  return next_stream_period != NULL;
+}
+
+void
+gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient * client,
+    guint segment_idx)
+{
+  GList *list;
+
+  g_return_if_fail (client != NULL);
+  g_return_if_fail (client->active_streams != NULL);
+
+  /* FIXME: support multiple streams with different segment duration */
+  for (list = g_list_first (client->active_streams); list;
+      list = g_list_next (list)) {
+    GstActiveStream *stream = (GstActiveStream *) list->data;
+    if (stream) {
+      stream->segment_idx = segment_idx;
+    }
+  }
+}
+
+gboolean
+gst_mpd_client_set_next_baseURL_for_stream (GstMpdClient * client)
+{
+  GstActiveStream *stream;
+  GstStreamPeriod *stream_period;
+  GList *list;
+
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (client->active_streams != NULL, FALSE);
+
+  stream = g_list_nth_data (client->active_streams,
+                           client->stream_idx);
+  g_return_val_if_fail (stream != NULL, FALSE);
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, FALSE);
+
+  if ((list = stream->cur_representation->BaseURLs) != NULL &&
+      stream->repr_baseURL_idx < g_list_length (list) - 1) {
+    stream->repr_baseURL_idx++;
+  } else if ((list = stream->cur_adapt_set->BaseURLs) != NULL &&
+            stream->adaptset_baseURL_idx < g_list_length (list) - 1) {
+    stream->adaptset_baseURL_idx++;
+    stream->repr_baseURL_idx = 0;
+  } else if ((list = stream_period->period->BaseURLs) != NULL &&
+            stream->period_baseURL_idx < g_list_length (list) - 1) {
+    stream->period_baseURL_idx++;
+    stream->adaptset_baseURL_idx = 0;
+    stream->repr_baseURL_idx = 0;
+  } else if ((list = client->mpd_node->BaseURLs) != NULL &&
+            stream->mpd_baseURL_idx < g_list_length (list) - 1) {
+      stream->mpd_baseURL_idx++;
+      stream->period_baseURL_idx = 0;
+      stream->adaptset_baseURL_idx = 0;
+      stream->repr_baseURL_idx = 0;
+  } else {
+    GST_WARNING ("Unable to change URI: No alternative baseURL available");
+    return FALSE;
+  }
+
+  stream->baseURL = gst_mpdparser_parse_baseURL (client);
+
+  return TRUE;
+}
+
+void
+gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx)
+{
+  g_return_if_fail (stream != NULL);
+
+  stream->segment_idx = segment_idx;
+}
+
+guint
+gst_mpd_client_get_segment_index (GstActiveStream * stream)
+{
+  g_return_val_if_fail (stream != NULL, 0);
+
+  return stream->segment_idx;
+}
+
+gboolean
+gst_mpd_client_is_live (GstMpdClient * client)
+{
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (client->mpd_node != NULL, FALSE);
+
+  return client->mpd_node->type == GST_MPD_FILE_TYPE_DYNAMIC;
+}
+
+guint
+gst_mpdparser_get_nb_active_stream (GstMpdClient * client)
+{
+  g_return_val_if_fail (client != NULL, 0);
+
+  return g_list_length (client->active_streams);
+}
+
+guint
+gst_mpdparser_get_nb_adaptationSet (GstMpdClient * client)
+{
+  GstStreamPeriod *stream_period;
+
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, 0);
+  g_return_val_if_fail (stream_period->period != NULL, 0);
+
+  return g_list_length (stream_period->period->AdaptationSets);
+}
+
+GstActiveStream *
+gst_mpdparser_get_active_stream_by_index (GstMpdClient * client,
+    guint stream_idx)
+{
+  g_return_val_if_fail (client != NULL, NULL);
+  g_return_val_if_fail (client->active_streams != NULL, NULL);
+
+  return g_list_nth_data (client->active_streams, stream_idx);
+}
+
+gint
+gst_mpd_client_get_video_active_stream_id(GstMpdClient *client) {
+  guint idx;
+  g_return_val_if_fail (client != NULL, -1);
+  g_return_val_if_fail (client->active_streams != NULL, -1);
+  for (idx = 0; idx < gst_mpdparser_get_nb_active_stream(client); idx++) {
+   GstActiveStream *stream = gst_mpdparser_get_active_stream_by_index(client, idx);
+   if( strncmp_ext (gst_mpd_client_get_stream_mimeType (stream), "video") == 0 )
+     return idx;
+  }
+  return -1;
+}
+
+gboolean
+gst_mpd_client_stream_seek (GstMpdClient * client, gint stream_idx, GstClockTime ts)
+{
+  guint segment_idx = 0;
+  GstActiveStream *stream;
+  GST_MPD_CLIENT_LOCK (client);
+  GST_DEBUG ("mpd client seeking to %"GST_TIME_FORMAT" on stream %d", GST_TIME_ARGS(ts), stream_idx);
+  stream = gst_mpdparser_get_active_stream_by_index (client, stream_idx);
+  g_return_val_if_fail (stream != NULL, FALSE);
+
+  if ( GST_CLOCK_TIME_IS_VALID (gst_mpd_client_stream_find_segment (client,
+          stream_idx, ts, &segment_idx))) {
+    gst_mpd_client_set_segment_index(stream, segment_idx);
+  }
+  GST_MPD_CLIENT_UNLOCK (client);
+  return TRUE;
+}
+
+static GDateTime *
+_gst_date_time_to_g_date_time (GstDateTime * datetime)
+{
+  g_return_val_if_fail (datetime != NULL, NULL);
+  return g_date_time_new_utc ( gst_date_time_get_year (datetime), gst_date_time_get_month(datetime),
+         gst_date_time_get_day(datetime), gst_date_time_get_hour(datetime),
+         gst_date_time_get_minute(datetime),gst_date_time_get_second(datetime));
+}
+
+gboolean
+gst_mpd_client_seek_to_time (GstMpdClient * client, GDateTime * time)
+{
+  GDateTime *start =
+      _gst_date_time_to_g_date_time (client->mpd_node->availabilityStartTime);
+  GTimeSpan ts_microseconds;
+  GstClockTime ts;
+  gboolean ret = TRUE;
+  gint i;
+
+  g_return_val_if_fail (gst_mpd_client_is_live (client), 0);
+
+  ts_microseconds = g_date_time_difference (time, start);
+  g_date_time_unref (start);
+
+  ts = ts_microseconds * GST_USECOND;
+  for (i=0; i < g_list_length (client->active_streams); i++) {
+    ret = ret & gst_mpd_client_stream_seek (client, i, ts);
+  }
+  return ret;
+}
+
+gint
+gst_mpd_client_check_time_position (GstMpdClient * client,
+    GstActiveStream * stream, GstClockTime ts, gint64 * diff)
+{
+  GDateTime *now = g_date_time_new_now_utc ();
+  GDateTime *start =
+      _gst_date_time_to_g_date_time (client->mpd_node->availabilityStartTime);
+  GTimeSpan stream_now;
+  GTimeSpan ts_microseconds;
+  GstClockTime duration;
+
+  g_return_val_if_fail (gst_mpd_client_is_live (client), 0);
+
+  duration = gst_mpd_client_get_segment_duration (client, stream);
+  stream_now = g_date_time_difference (now, start);
+  g_date_time_unref (now);
+  g_date_time_unref (start);
+
+  /* sum duration to check if the segment is fully ready */
+  ts_microseconds = (ts + duration) / GST_USECOND;
+
+  /*
+   * This functions checks if a given ts is in the 'available range' of
+   * a DASH presentation. This only makes sense for live streams, which
+   * are continuously adding new segments and removing old ones.
+   *
+   * Note: Both the client and the server should use UTC as a time reference.
+   *
+   * @ts is the time since the beginning of the stream and we need to find out
+   * if it is currently available. The server should be hosting segments
+   *
+   * * ---------------- ... --- * ----------- * ---- ...
+   * |
+   * | past(unavailable) |      | available   | future(unavailable yet)
+   * |
+   * * ---------------- ... --- * ----------- * ---- ...
+   * |                          |             |
+   * availabilitStartTime       |             UTC now
+   *                            UTC now - timeShiftBufferDepth
+   *
+   * This function should return 0 if @ts is in the 'available' area, 1 for
+   * 'future' and '-1' for past and the corresponding distance to the
+   * 'available' area is set to @diff
+   *
+   * TODO untested with live presentations with multiple periods as no
+   * examples for it could be found/generated
+   */
+
+  if (ts_microseconds > stream_now) {
+    *diff = ts_microseconds - stream_now;
+    return 1;
+  }
+  if (GST_CLOCK_TIME_IS_VALID (client->mpd_node->timeShiftBufferDepth)
+      && ts_microseconds <
+      stream_now - client->mpd_node->timeShiftBufferDepth * GST_USECOND) {
+    *diff = ts_microseconds - stream_now;
+    return -1;
+  }
+
+  *diff = 0;
+  return 0;
+}
+
+/*Finds the segment with appropriate time*/
+GstClockTime
+gst_mpd_client_stream_find_segment(GstMpdClient *client, guint stream_idx,
+                                   GstClockTime seek_pos, guint *seg_num)
+{
+  guint cur_segment_idx=0;
+  GstMediaSegment *chunk;
+  GList *list = NULL;
+  GstClockTime current_pos = 0;
+  GstActiveStream *stream = gst_mpdparser_get_active_stream_by_index (client, stream_idx);
+  g_return_val_if_fail (stream != NULL, GST_CLOCK_TIME_NONE);
+  if(stream->segments != NULL) {
+    for (list = g_list_first (stream->segments); list;
+        list = g_list_next (list)) {
+      chunk = list->data;
+      current_pos = chunk->start_time;
+      if (current_pos <= seek_pos
+          && seek_pos < current_pos + chunk->duration) {
+        break;
+      }
+      cur_segment_idx++;
+    }
+    if(list != NULL) {
+      *seg_num = cur_segment_idx;
+      return current_pos;
+    } else {
+      return GST_CLOCK_TIME_NONE;
+    }
+  } else {
+    GstClockTime duration;
+    duration = gst_mpd_client_get_segment_duration (client, stream);
+    if( !GST_CLOCK_TIME_IS_VALID (duration) )
+      return FALSE;
+    *seg_num = seek_pos / duration;
+    return *seg_num * duration;
+  }
+}
+
+static const gchar *
+gst_mpdparser_mimetype_to_caps (const gchar * mimeType)
+{
+  if (mimeType == NULL)
+    return NULL;
+  if (strcmp (mimeType, "video/mp2t") == 0) {
+    return "video/mpegts";
+  } else if (strcmp (mimeType, "video/mp4") == 0) {
+    return "video/quicktime";
+  } else if (strcmp (mimeType, "audio/mp4") == 0) {
+    return "audio/x-m4a";
+  } else
+    return mimeType;
+}
+
+const gchar *
+gst_mpd_client_get_stream_mimeType (GstActiveStream * stream)
+{
+  const gchar *mimeType;
+
+  if (stream == NULL || stream->cur_adapt_set == NULL
+      || stream->cur_representation == NULL)
+    return NULL;
+
+  mimeType = stream->cur_representation->RepresentationBase->mimeType;
+  if (mimeType == NULL) {
+    mimeType = stream->cur_adapt_set->RepresentationBase->mimeType;
+  }
+
+  return gst_mpdparser_mimetype_to_caps (mimeType);
+}
+
+const gboolean
+gst_mpd_client_get_bitstream_switching_flag (GstActiveStream * stream)
+{
+  if (stream == NULL || stream->cur_adapt_set == NULL)
+    return FALSE;
+
+  return stream->cur_adapt_set->bitstreamSwitching;
+}
+
+gboolean
+gst_mpd_client_get_max_video_dimensions (GstMpdClient *client, gint *max_width, gint *max_height)
+{
+  GList *period_it, *repr_it;
+  GstStreamPeriod *period;
+  GstAdaptationSetNode *adaptset;
+  GstRepresentationNode *repr;
+
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (max_height != NULL, FALSE);
+  g_return_val_if_fail (max_width != NULL, FALSE);
+
+  *max_width = 0;
+  *max_height = 0;
+
+  period_it = client->periods;
+  while(period_it) {
+    period = period_it->data;
+    adaptset = gst_mpdparser_get_adapt_set_with_mimeType_and_idx (
+          period->period->AdaptationSets, "video", 0);
+    if(adaptset == NULL)
+      continue;
+    repr_it = adaptset->Representations;
+
+    if(adaptset->RepresentationBase->width > *max_width)
+      *max_width = adaptset->RepresentationBase->width;
+    if(adaptset->RepresentationBase->height > *max_height)
+      *max_height = adaptset->RepresentationBase->height;
+
+    while(repr_it) {
+      repr = repr_it->data;
+      if(repr->RepresentationBase->width > *max_width)
+        *max_width = repr->RepresentationBase->width;
+      if(repr->RepresentationBase->height > *max_height)
+        *max_height = repr->RepresentationBase->height;
+      repr_it = repr_it->next;
+    }
+
+    period_it = period_it->next;
+  }
+  if(*max_width == 0 && *max_height == 0)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+guint
+gst_mpd_client_get_video_stream_width (GstActiveStream * stream)
+{
+  guint width;
+
+  if (stream == NULL || stream->cur_adapt_set == NULL
+      || stream->cur_representation == NULL)
+    return 0;
+
+  width = stream->cur_representation->RepresentationBase->width;
+  if (width == 0) {
+    width = stream->cur_adapt_set->RepresentationBase->width;
+  }
+
+  return width;
+}
+
+guint
+gst_mpd_client_get_video_stream_height (GstActiveStream * stream)
+{
+  guint height;
+
+  if (stream == NULL || stream->cur_adapt_set == NULL
+      || stream->cur_representation == NULL)
+    return 0;
+
+  height = stream->cur_representation->RepresentationBase->height;
+  if (height == 0) {
+    height = stream->cur_adapt_set->RepresentationBase->height;
+  }
+
+  return height;
+}
+
+guint
+gst_mpd_client_get_video_stream_bandwidth (GstActiveStream * stream)
+{
+  guint bandwidth;
+
+  if (stream == NULL || stream->cur_adapt_set == NULL
+      || stream->cur_representation == NULL)
+    return 0;
+
+  bandwidth = stream->cur_representation->RepresentationBase->bandwidth;
+  if (bandwidth == 0) {
+    bandwidth = stream->cur_adapt_set->RepresentationBase->bandwidth;
+  }
+
+  return bandwidth;
+}
+
+guint
+gst_mpd_client_get_audio_stream_rate (GstActiveStream * stream)
+{
+  const gchar *rate;
+
+  if (stream == NULL || stream->cur_adapt_set == NULL
+      || stream->cur_representation == NULL)
+    return 0;
+
+  rate = stream->cur_representation->RepresentationBase->audioSamplingRate;
+  if (rate == NULL) {
+    rate = stream->cur_adapt_set->RepresentationBase->audioSamplingRate;
+  }
+
+  return rate ? atoi (rate) : 0;
+}
+
+guint
+gst_mpd_client_get_audio_stream_num_channels (GstActiveStream * stream)
+{
+  if (stream == NULL || stream->cur_adapt_set == NULL
+      || stream->cur_representation == NULL)
+    return 0;
+  /* TODO: here we have to parse the AudioChannelConfiguration descriptors */
+  return 0;
+}
+
+guint
+gst_mpdparser_get_list_and_nb_of_audio_language (GstMpdClient * client,
+    GList ** lang)
+{
+  GstStreamPeriod *stream_period;
+  GstAdaptationSetNode *adapt_set;
+  GList *list;
+  gchar *this_mimeType = "audio";
+  gchar *mimeType = NULL;
+  guint nb_adapatation_set = 0;
+
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, 0);
+  g_return_val_if_fail (stream_period->period != NULL, 0);
+
+  for (list = g_list_first (stream_period->period->AdaptationSets); list;
+      list = g_list_next (list)) {
+    adapt_set = (GstAdaptationSetNode *) list->data;
+    if (adapt_set) {
+      gchar *this_lang = adapt_set->lang;
+      GstRepresentationNode *rep;
+      rep =
+          gst_mpdparser_get_lowest_representation (adapt_set->Representations);
+      if (!rep) {
+        GST_WARNING ("No valid representation in the MPD file, aborting...");
+        return 0;
+      }
+      if (rep->RepresentationBase)
+        mimeType = rep->RepresentationBase->mimeType;
+      if (!mimeType && adapt_set->RepresentationBase) {
+        mimeType = adapt_set->RepresentationBase->mimeType;
+      }
+
+      if (strncmp_ext (mimeType, this_mimeType) == 0) {
+        if (this_lang) {
+          nb_adapatation_set++;
+          *lang = g_list_append (*lang, this_lang);
+        }
+      }
+    }
+  }
+
+  return nb_adapatation_set;
+}
diff --git a/dashdemux/src/gstmpdparser.h b/dashdemux/src/gstmpdparser.h
new file mode 100755 (executable)
index 0000000..3231d62
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ * DASH MPD parsing library
+ *
+ * gstmpdparser.h
+ *
+ * Copyright (C) 2012 STMicroelectronics
+ *
+ * Authors:
+ *   Gianluca Gennari <gennarone@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_MPDPARSER_H__
+#define __GST_MPDPARSER_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstMpdClient              GstMpdClient;
+typedef struct _GstActiveStream           GstActiveStream;
+typedef struct _GstStreamPeriod           GstStreamPeriod;
+typedef struct _GstMediaSegment           GstMediaSegment;
+typedef struct _GstMPDNode                GstMPDNode;
+typedef struct _GstPeriodNode             GstPeriodNode;
+typedef struct _GstRepresentationBaseType GstRepresentationBaseType;
+typedef struct _GstDescriptorType         GstDescriptorType;
+typedef struct _GstContentComponentNode   GstContentComponentNode;
+typedef struct _GstAdaptationSetNode      GstAdaptationSetNode;
+typedef struct _GstRepresentationNode     GstRepresentationNode;
+typedef struct _GstSubRepresentationNode  GstSubRepresentationNode;
+typedef struct _GstSegmentListNode        GstSegmentListNode;
+typedef struct _GstSegmentTemplateNode    GstSegmentTemplateNode;
+typedef struct _GstSegmentURLNode         GstSegmentURLNode;
+typedef struct _GstBaseURL                GstBaseURL;
+typedef struct _GstRange                  GstRange;
+typedef struct _GstRatio                  GstRatio;
+typedef struct _GstFrameRate              GstFrameRate;
+typedef struct _GstConditionalUintType    GstConditionalUintType;
+typedef struct _GstSubsetNode             GstSubsetNode;
+typedef struct _GstProgramInformationNode GstProgramInformationNode;
+typedef struct _GstMetricsRangeNode       GstMetricsRangeNode;
+typedef struct _GstMetricsNode            GstMetricsNode;
+typedef struct _GstSNode                  GstSNode;
+typedef struct _GstSegmentTimelineNode    GstSegmentTimelineNode;
+typedef struct _GstSegmentBaseType        GstSegmentBaseType;
+typedef struct _GstURLType                GstURLType;
+typedef struct _GstMultSegmentBaseType    GstMultSegmentBaseType;
+
+#define GST_MPD_CLIENT_LOCK(c) g_mutex_lock (c->lock);
+#define GST_MPD_CLIENT_UNLOCK(c) g_mutex_unlock (c->lock);
+
+typedef enum
+{
+  GST_STREAM_VIDEO,           /* video stream (the main one) */
+  GST_STREAM_AUDIO,           /* audio stream (optional) */
+  GST_STREAM_APPLICATION      /* application stream (optional): for timed text/subtitles */
+} GstStreamMimeType;
+
+typedef enum
+{
+  GST_MPD_FILE_TYPE_STATIC,
+  GST_MPD_FILE_TYPE_DYNAMIC
+} GstMPDFileType;
+
+typedef enum
+{
+  GST_SAP_TYPE_0 = 0,
+  GST_SAP_TYPE_1,
+  GST_SAP_TYPE_2,
+  GST_SAP_TYPE_3,
+  GST_SAP_TYPE_4,
+  GST_SAP_TYPE_5,
+  GST_SAP_TYPE_6
+} GstSAPType;
+
+struct _GstBaseURL
+{
+  gchar *baseURL;
+  gchar *serviceLocation;
+  gchar *byteRange;
+};
+
+struct _GstRange
+{
+  guint64 first_byte_pos;
+  guint64 last_byte_pos;
+};
+
+struct _GstRatio
+{
+  guint num;
+  guint den;
+};
+
+struct _GstFrameRate
+{
+  guint num;
+  guint den;
+};
+
+struct _GstConditionalUintType
+{
+  gboolean flag;
+  guint value;
+};
+
+struct _GstSNode
+{
+  guint t;
+  guint d;
+  guint r;
+};
+
+struct _GstSegmentTimelineNode
+{
+  /* list of S nodes */
+  GList *S;
+};
+
+struct _GstURLType
+{
+  gchar *sourceURL;
+  GstRange *range;
+};
+
+struct _GstSegmentBaseType
+{
+  guint timescale;
+  guint presentationTimeOffset;
+  gchar *indexRange;
+  gboolean indexRangeExact;
+  /* Initialization node */
+  GstURLType *Initialization;
+  /* RepresentationIndex node */
+  GstURLType *RepresentationIndex;
+};
+
+struct _GstMultSegmentBaseType
+{
+  guint duration;                  /* in seconds */
+  guint startNumber;
+  /* SegmentBaseType extension */
+  GstSegmentBaseType *SegBaseType;
+  /* SegmentTimeline node */
+  GstSegmentTimelineNode *SegmentTimeline;
+  /* BitstreamSwitching node */
+  GstURLType *BitstreamSwitching;
+};
+
+struct _GstSegmentListNode
+{
+  /* extension */
+  GstMultSegmentBaseType *MultSegBaseType;
+  /* list of SegmentURL nodes */
+  GList *SegmentURL;
+};
+
+struct _GstSegmentTemplateNode
+{
+  /* extension */
+  GstMultSegmentBaseType *MultSegBaseType;
+  gchar *media;
+  gchar *index;
+  gchar *initialization;
+  gchar *bitstreamSwitching;
+};
+
+struct _GstSegmentURLNode
+{
+  gchar *media;
+  GstRange *mediaRange;
+  gchar *index;
+  GstRange *indexRange;
+};
+
+struct _GstRepresentationBaseType
+{
+  gchar *profiles;
+  guint width;
+  guint height;
+  guint bandwidth;
+  GstRatio *sar;
+  GstFrameRate *frameRate;
+  gchar *audioSamplingRate;
+  gchar *mimeType;
+  gchar *segmentProfiles;
+  gchar *codecs;
+  gdouble maximumSAPPeriod;
+  GstSAPType startWithSAP;
+  gdouble maxPlayoutRate;
+  gboolean codingDependency;
+  gchar *scanType;
+  /* list of FramePacking DescriptorType nodes */
+  GList *FramePacking;
+  /* list of AudioChannelConfiguration DescriptorType nodes */
+  GList *AudioChannelConfiguration;
+  /* list of ContentProtection DescriptorType nodes */
+  GList *ContentProtection;
+};
+
+struct _GstSubRepresentationNode
+{
+  /* RepresentationBase extension */
+  GstRepresentationBaseType *RepresentationBase;
+  guint level;
+  guint *dependencyLevel;            /* UIntVectorType */
+  guint size;                        /* size of "dependencyLevel" array */
+  guint64 bandwidth;
+  gchar **contentComponent;          /* StringVectorType */
+};
+
+struct _GstRepresentationNode
+{
+  gchar *id;
+  guint bandwidth;
+  guint qualityRanking;
+  gchar **dependencyId;              /* StringVectorType */
+  gchar **mediaStreamStructureId;    /* StringVectorType */
+  /* RepresentationBase extension */
+  GstRepresentationBaseType *RepresentationBase;
+  /* list of BaseURL nodes */
+  GList *BaseURLs;
+  /* list of SubRepresentation nodes */
+  GList *SubRepresentations;
+  /* SegmentBase node */
+  GstSegmentBaseType *SegmentBase;
+  /* SegmentTemplate node */
+  GstSegmentTemplateNode *SegmentTemplate;
+  /* SegmentList node */
+  GstSegmentListNode *SegmentList;
+};
+
+struct _GstDescriptorType
+{
+  gchar *schemeIdUri;
+  gchar *value;
+  /* For adding ContentProtection to caps , get string of <mspr:pro> */
+  gchar *msprPro;
+};
+
+struct _GstContentComponentNode
+{
+  guint id;
+  gchar *lang;                      /* LangVectorType RFC 5646 */
+  gchar *contentType;
+  GstRatio *par;
+  /* list of Accessibility DescriptorType nodes */
+  GList *Accessibility;
+  /* list of Role DescriptorType nodes */
+  GList *Role;
+  /* list of Rating DescriptorType nodes */
+  GList *Rating;
+  /* list of Viewpoint DescriptorType nodes */
+  GList *Viewpoint;
+};
+
+struct _GstAdaptationSetNode
+{
+  guint id;
+  guint group;
+  gchar *lang;                      /* LangVectorType RFC 5646 */
+  gchar *contentType;
+  GstRatio *par;
+  guint minBandwidth;
+  guint maxBandwidth;
+  guint minWidth;
+  guint maxWidth;
+  guint minHeight;
+  guint maxHeight;
+  GstFrameRate *minFrameRate;
+  GstFrameRate *maxFrameRate;
+  GstConditionalUintType *segmentAlignment;
+  GstConditionalUintType *subsegmentAlignment;
+  GstSAPType subsegmentStartsWithSAP;
+  gboolean bitstreamSwitching;
+  /* list of Accessibility DescriptorType nodes */
+  GList *Accessibility;
+  /* list of Role DescriptorType nodes */
+  GList *Role;
+  /* list of Rating DescriptorType nodes */
+  GList *Rating;
+  /* list of Viewpoint DescriptorType nodes */
+  GList *Viewpoint;
+  /* RepresentationBase extension */
+  GstRepresentationBaseType *RepresentationBase;
+  /* SegmentBase node */
+  GstSegmentBaseType *SegmentBase;
+  /* SegmentList node */
+  GstSegmentListNode *SegmentList;
+  /* SegmentTemplate node */
+  GstSegmentTemplateNode *SegmentTemplate;
+  /* list of BaseURL nodes */
+  GList *BaseURLs;
+  /* list of Representation nodes */
+  GList *Representations;
+  /* list of ContentComponent nodes */
+  GList *ContentComponents;
+};
+
+struct _GstSubsetNode
+{
+  guint *contains;                   /* UIntVectorType */
+  guint size;                        /* size of the "contains" array */
+};
+
+struct _GstPeriodNode
+{
+  gchar *id;
+  gint64 start;                      /* [ms] */
+  gint64 duration;                   /* [ms] */
+  gboolean bitstreamSwitching;
+  /* SegmentBase node */
+  GstSegmentBaseType *SegmentBase;
+  /* SegmentList node */
+  GstSegmentListNode *SegmentList;
+  /* SegmentTemplate node */
+  GstSegmentTemplateNode *SegmentTemplate;
+  /* list of Adaptation Set nodes */
+  GList *AdaptationSets;
+  /* list of Representation nodes */
+  GList *Subsets;
+  /* list of BaseURL nodes */
+  GList *BaseURLs;
+};
+
+struct _GstProgramInformationNode
+{
+  gchar *lang;                      /* LangVectorType RFC 5646 */
+  gchar *moreInformationURL;
+  /* children nodes */
+  gchar *Title;
+  gchar *Source;
+  gchar *Copyright;
+};
+
+struct _GstMetricsRangeNode
+{
+  gint64 starttime;                  /* [ms] */
+  gint64 duration;                   /* [ms] */
+};
+
+struct _GstMetricsNode
+{
+  gchar *metrics;
+  /* list of Metrics Range nodes */
+  GList *MetricsRanges;
+  /* list of Reporting nodes */
+  GList *Reportings;
+};
+
+struct _GstMPDNode
+{
+  gchar *default_namespace;
+  gchar *namespace_xsi;
+  gchar *namespace_ext;
+  gchar *schemaLocation;
+  gchar *id;
+  gchar *profiles;
+  GstMPDFileType type;
+  GstDateTime *availabilityStartTime;
+  GstDateTime *availabilityEndTime;
+  gint64 mediaPresentationDuration;  /* [ms] */
+  gint64 minimumUpdatePeriod;        /* [ms] */
+  gint64 minBufferTime;              /* [ms] */
+  gint64 timeShiftBufferDepth;       /* [ms] */
+  gint64 suggestedPresentationDelay; /* [ms] */
+  gint64 maxSegmentDuration;         /* [ms] */
+  gint64 maxSubsegmentDuration;      /* [ms] */
+  /* list of BaseURL nodes */
+  GList *BaseURLs;
+  /* list of Location nodes */
+  GList *Locations;
+  /* List of ProgramInformation nodes */
+  GList *ProgramInfo;
+  /* list of Periods nodes */
+  GList *Periods;
+  /* list of Metrics nodes */
+  GList *Metrics;
+};
+
+/**
+ * GstStreamPeriod:
+ *
+ * Stream period data structure
+ */
+struct _GstStreamPeriod
+{
+  GstPeriodNode *period;                      /* Stream period */
+  guint number;                               /* Period number */
+  GstClockTime start;                         /* Period start time */
+  GstClockTime duration;                      /* Period duration */
+};
+
+/**
+ * GstMediaSegment:
+ *
+ * Media segment data structure
+ */
+struct _GstMediaSegment
+{
+  GstSegmentURLNode *SegmentURL;              /* this is NULL when using a SegmentTemplate */
+  guint number;                               /* segment number */
+  guint start;                                /* segment start time in timescale units */
+  GstClockTime start_time;                    /* segment start time */
+  GstClockTime duration;                      /* segment duration */
+};
+
+/**
+ * GstActiveStream:
+ *
+ * Active stream data structure
+ */
+struct _GstActiveStream
+{
+  GstStreamMimeType mimeType;                 /* video/audio/application */
+
+  guint mpd_baseURL_idx;                      /* MPD baseURL index */
+  guint period_baseURL_idx;                   /* Period baseURL index */
+  guint adaptset_baseURL_idx;                 /* AdaptationSet baseURL index */
+  guint repr_baseURL_idx;                     /* Representation baseURL index */
+
+  gchar *baseURL;                             /* active baseURL used for last request */
+  guint max_bandwidth;                        /* max bandwidth allowed for this mimeType */
+
+  GstAdaptationSetNode *cur_adapt_set;        /* active adaptation set */
+  gint representation_idx;                    /* index of current representation */
+  GstRepresentationNode *cur_representation;  /* active representation */
+  GstSegmentBaseType *cur_segment_base;       /* active segment base */
+  GstSegmentListNode *cur_segment_list;       /* active segment list */
+  GstSegmentTemplateNode *cur_seg_template;   /* active segment template */
+  guint segment_idx;                          /* index of next sequence chunk */
+  GList *segments;                            /* list of GstMediaSegment */
+};
+
+struct _GstMpdClient
+{
+  GstMPDNode *mpd_node;                       /* active MPD manifest file */
+
+  GList *periods;                             /* list of GstStreamPeriod */
+  guint period_idx;                           /* index of current Period */
+
+  GList *active_streams;                      /* list of GstActiveStream */
+  guint stream_idx;                           /* currently active stream */
+
+  guint download_failed_count;
+  gchar *mpd_uri;                             /* manifest file URI */
+  GMutex *lock;
+};
+
+/* Basic initialization/deinitialization functions */
+GstMpdClient *gst_mpd_client_new ();
+void gst_active_streams_free (GstMpdClient * client);
+void gst_mpd_client_free (GstMpdClient * client);
+
+/* MPD file parsing */
+gboolean gst_mpd_parse (GstMpdClient *client, const gchar *data, gint size);
+
+/* Streaming management */
+gboolean gst_mpd_client_setup_media_presentation (GstMpdClient *client);
+gboolean gst_mpd_client_setup_streaming (GstMpdClient *client, GstStreamMimeType mimeType, gchar* lang);
+gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation);
+gboolean gst_mpd_client_get_stream_current_position (GstMpdClient * client, guint stream_idx, GstClockTime *ts);
+GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client);
+GstClockTime gst_mpd_client_get_media_presentation_duration (GstMpdClient *client);
+gboolean gst_mpd_client_get_next_fragment (GstMpdClient *client, guint indexStream, gboolean *discontinuity, gchar **uri, GstClockTime *duration, GstClockTime *timestamp);
+gboolean gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
+gboolean gst_mpd_client_get_next_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
+gboolean gst_mpd_client_get_next_header (GstMpdClient *client, const gchar **uri, guint stream_idx);
+gboolean gst_mpd_client_is_live (GstMpdClient * client);
+
+/* Period selection */
+gboolean gst_mpd_client_set_period_index (GstMpdClient *client, guint period_idx);
+guint gst_mpd_client_get_period_index (GstMpdClient *client);
+const gchar* gst_mpd_client_get_period_id (GstMpdClient * client);
+gboolean gst_mpd_client_set_period_id (GstMpdClient * client, const gchar * period_id);
+gboolean gst_mpd_client_has_next_period (GstMpdClient * client);
+
+/* Representation selection */
+gint gst_mpdparser_get_rep_idx_with_max_bandwidth (GList *Representations, guint64 max_bandwidth);
+
+/* URL management */
+const gchar *gst_mpdparser_get_baseURL (GstMpdClient *client);
+gboolean gst_mpdparser_get_chunk_by_index (GstMpdClient * client, guint indexStream, guint indexChunk, GstMediaSegment *segment);
+gboolean gst_mpd_client_set_next_baseURL_for_stream (GstMpdClient * client);
+
+/* Active stream */
+guint gst_mpdparser_get_nb_active_stream (GstMpdClient *client);
+GstActiveStream *gst_mpdparser_get_active_stream_by_index (GstMpdClient *client, guint stream_idx);
+gint gst_mpd_client_get_video_active_stream_id(GstMpdClient *client);
+gboolean gst_mpd_client_stream_seek (GstMpdClient * client, gint stream_idx, GstClockTime ts);
+gboolean gst_mpd_client_seek_to_time (GstMpdClient * client, GDateTime * time);
+gint gst_mpd_client_check_time_position (GstMpdClient * client, GstActiveStream * stream, GstClockTime ts, gint64 * diff);
+GstClockTime gst_mpd_client_stream_find_segment(GstMpdClient *client, guint stream_idx, GstClockTime seek_pos, guint *seg_num);
+
+/* AdaptationSet */
+guint gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client);
+
+/* Segment */
+void gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient * client, guint segment_idx);
+void gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx);
+guint gst_mpd_client_get_segment_index (GstActiveStream * stream);
+
+/* Get audio/video stream parameters (mimeType, width, height, rate, number of channels) */
+const gchar *gst_mpd_client_get_stream_mimeType (GstActiveStream * stream);
+const gboolean gst_mpd_client_get_bitstream_switching_flag (GstActiveStream * stream);
+gboolean gst_mpd_client_get_max_video_dimensions(GstMpdClient *client, gint *max_width, gint *max_height);
+guint gst_mpd_client_get_video_stream_width (GstActiveStream * stream);
+guint gst_mpd_client_get_video_stream_height (GstActiveStream * stream);
+guint gst_mpd_client_get_video_stream_bandwidth (GstActiveStream * stream);
+guint gst_mpd_client_get_audio_stream_rate (GstActiveStream * stream);
+guint gst_mpd_client_get_audio_stream_num_channels (GstActiveStream * stream);
+
+/* Support multi language */
+guint gst_mpdparser_get_list_and_nb_of_audio_language (GstMpdClient *client, GList **lang);
+G_END_DECLS
+
+#endif /* __GST_MPDPARSER_H__ */
diff --git a/dashdemux/src/gstplugin.c b/dashdemux/src/gstplugin.c
new file mode 100755 (executable)
index 0000000..8584caf
--- /dev/null
@@ -0,0 +1,109 @@
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <string.h>
+
+#include <gst/gst.h>
+
+#include "gstfragmented.h"
+#include "gstdashdemux.h"
+
+GST_DEBUG_CATEGORY (fragmented_debug);
+
+#define XML_BUFFER_SIZE 16
+#define XML_INC_BUFFER {                                                \
+  pos++;                                                                \
+  if (pos == XML_BUFFER_SIZE) {                                         \
+    pos = 0;                                                            \
+    offset += XML_BUFFER_SIZE;                                          \
+    data = gst_type_find_peek (tf, offset, XML_BUFFER_SIZE);            \
+    if (data == NULL) return FALSE;                                     \
+  } else {                                                              \
+    data++;                                                             \
+  }                                                                     \
+}
+
+static gboolean
+xml_check_first_element (GstTypeFind * tf, const gchar * element, guint elen,
+    gboolean strict)
+{
+  gboolean got_xmldec;
+  const guint8 *data;
+  guint offset = 0;
+  guint pos = 0;
+
+  data = gst_type_find_peek (tf, 0, XML_BUFFER_SIZE);
+  if (!data)
+    return FALSE;
+
+  /* look for the XMLDec
+   * see XML spec 2.8, Prolog and Document Type Declaration
+   * http://www.w3.org/TR/2004/REC-xml-20040204/#sec-prolog-dtd */
+  got_xmldec = (memcmp (data, "<?xml", 5) == 0);
+
+  if (strict && !got_xmldec)
+    return FALSE;
+
+  /* skip XMLDec in any case if we've got one */
+  if (got_xmldec) {
+    pos += 5;
+    data += 5;
+  }
+
+  /* look for the first element, it has to be the requested element. Bail
+   * out if it is not within the first 4kB. */
+  while (data && (offset + pos) < 4096) {
+    while (*data != '<' && (offset + pos) < 4096) {
+      XML_INC_BUFFER;
+    }
+
+    XML_INC_BUFFER;
+    if (!g_ascii_isalpha (*data)) {
+      /* if not alphabetic, it's a PI or an element / attribute declaration
+       * like <?xxx or <!xxx */
+      XML_INC_BUFFER;
+      continue;
+    }
+
+    /* the first normal element, check if it's the one asked for */
+    data = gst_type_find_peek (tf, offset + pos, elen + 1);
+    return (data && element && strncmp ((char *) data, element, elen) == 0);
+  }
+
+  return FALSE;
+}
+
+/*** application/dash+xml typefind helper ***/
+
+static GstStaticCaps dash_caps = GST_STATIC_CAPS ("application/dash+xml");
+
+#define DASH_CAPS gst_static_caps_get (&dash_caps)
+
+static void
+dash_type_find (GstTypeFind * tf, gpointer unused)
+{
+  if (xml_check_first_element (tf, "MPD", 3, FALSE) ||
+      xml_check_first_element (tf, "mpd", 3, FALSE)) {
+    gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, DASH_CAPS);
+  }
+}
+
+static gboolean
+fragmented_init (GstPlugin * plugin)
+{
+  GST_DEBUG_CATEGORY_INIT (fragmented_debug, "dashdemux", 0, "dashdemux");
+  if (!gst_element_register (plugin, "dashdemux", GST_RANK_PRIMARY,
+          GST_TYPE_DASH_DEMUX) || FALSE)
+    return FALSE;
+  if(!gst_type_find_register (plugin, "application/dash+xml",
+      GST_RANK_SECONDARY, dash_type_find, NULL, DASH_CAPS, NULL, NULL))
+    return FALSE;
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "dashdemux",
+    "DASH demuxer plugin",
+    fragmented_init, VERSION, "LGPL", PACKAGE_NAME, "http://www.gstreamer.org/")
diff --git a/dashdemux/src/gsturidownloader.c b/dashdemux/src/gsturidownloader.c
new file mode 100755 (executable)
index 0000000..0f7375d
--- /dev/null
@@ -0,0 +1,401 @@
+/* GStreamer
+ * Copyright (C) 2011 Andoni Morales Alastruey <ylatuya@gmail.com>
+ *
+ * gstfragment.c:
+ *
+ * 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 <glib.h>
+#include "gstfragmented.h"
+#include "gstfragment.h"
+#include "gsturidownloader.h"
+
+GST_DEBUG_CATEGORY_STATIC (uridownloader_debug);
+#define GST_CAT_DEFAULT (uridownloader_debug)
+
+#define GST_URI_DOWNLOADER_GET_PRIVATE(obj)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+    GST_TYPE_URI_DOWNLOADER, GstUriDownloaderPrivate))
+
+struct _GstUriDownloaderPrivate
+{
+  /* Fragments fetcher */
+  GstElement *urisrc;
+  GstBus *bus;
+  GstPad *pad;
+  GTimeVal *timeout;
+  GstFragment *download;
+  GMutex *lock;
+  GCond *cond;
+  gboolean canceled;
+/* add setting UA,cookies */
+  gchar *user_agent;
+  gchar **cookies;
+};
+
+static void gst_uri_downloader_finalize (GObject * object);
+static void gst_uri_downloader_dispose (GObject * object);
+
+static GstFlowReturn gst_uri_downloader_chain (GstPad * pad, GstBuffer * buf);
+static gboolean gst_uri_downloader_sink_event (GstPad * pad, GstEvent * event);
+static GstBusSyncReply gst_uri_downloader_bus_handler (GstBus * bus,
+    GstMessage * message, gpointer data);
+
+static GstStaticPadTemplate sinkpadtemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+#define _do_init \
+{ \
+  GST_DEBUG_CATEGORY_INIT (uridownloader_debug, "uridownloader", 0, "URI downloader"); \
+}
+
+G_DEFINE_TYPE_WITH_CODE (GstUriDownloader, gst_uri_downloader, GST_TYPE_OBJECT,
+    _do_init);
+
+static void
+gst_uri_downloader_class_init (GstUriDownloaderClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+
+  g_type_class_add_private (klass, sizeof (GstUriDownloaderPrivate));
+
+  gobject_class->dispose = gst_uri_downloader_dispose;
+  gobject_class->finalize = gst_uri_downloader_finalize;
+}
+
+static void
+gst_uri_downloader_init (GstUriDownloader * downloader)
+{
+  downloader->priv = GST_URI_DOWNLOADER_GET_PRIVATE (downloader);
+
+  /* Initialize the sink pad. This pad will be connected to the src pad of the
+   * element created with gst_element_make_from_uri and will handle the download */
+  downloader->priv->pad =
+      gst_pad_new_from_static_template (&sinkpadtemplate, "sink");
+  gst_pad_set_chain_function (downloader->priv->pad,
+      GST_DEBUG_FUNCPTR (gst_uri_downloader_chain));
+  gst_pad_set_event_function (downloader->priv->pad,
+      GST_DEBUG_FUNCPTR (gst_uri_downloader_sink_event));
+  gst_pad_set_element_private (downloader->priv->pad, downloader);
+  gst_pad_activate_push (downloader->priv->pad, TRUE);
+
+  /* Create a bus to handle error and warning message from the source element */
+  downloader->priv->bus = gst_bus_new ();
+
+  downloader->priv->lock = g_mutex_new ();
+  downloader->priv->cond = g_cond_new ();
+/* add setting UA, cookies */
+  downloader->priv->user_agent = NULL;
+  downloader->priv->cookies = NULL;
+  downloader->priv->canceled = FALSE;
+}
+
+void
+gst_uri_downloader_reset(GstUriDownloader *downloader)
+{
+  downloader->priv->canceled = FALSE;
+}
+
+static void
+gst_uri_downloader_dispose (GObject * object)
+{
+  GstUriDownloader *downloader = GST_URI_DOWNLOADER (object);
+
+  if (downloader->priv->urisrc != NULL) {
+    gst_object_unref (downloader->priv->urisrc);
+    downloader->priv->urisrc = NULL;
+  }
+
+  if (downloader->priv->bus != NULL) {
+    gst_object_unref (downloader->priv->bus);
+    downloader->priv->bus = NULL;
+  }
+
+  if (downloader->priv->pad) {
+    gst_object_unref (downloader->priv->pad);
+    downloader->priv->pad = NULL;
+  }
+
+  if (downloader->priv->download) {
+    g_object_unref (downloader->priv->download);
+    downloader->priv->download = NULL;
+  }
+
+/* add setting UA, cookies */
+  if (downloader->priv->user_agent) {
+    g_free (downloader->priv->user_agent);
+    downloader->priv->user_agent = NULL;
+  }
+  if (downloader->priv->cookies) {
+    g_strfreev (downloader->priv->cookies);
+    downloader->priv->cookies = NULL;
+  }
+  G_OBJECT_CLASS (gst_uri_downloader_parent_class)->dispose (object);
+}
+
+static void
+gst_uri_downloader_finalize (GObject * object)
+{
+  GstUriDownloader *downloader = GST_URI_DOWNLOADER (object);
+
+  g_mutex_free (downloader->priv->lock);
+  g_cond_free (downloader->priv->cond);
+
+  G_OBJECT_CLASS (gst_uri_downloader_parent_class)->finalize (object);
+}
+
+GstUriDownloader *
+gst_uri_downloader_new (void)
+{
+  return g_object_new (GST_TYPE_URI_DOWNLOADER, NULL);
+}
+
+static gboolean
+gst_uri_downloader_sink_event (GstPad * pad, GstEvent * event)
+{
+  GstUriDownloader *downloader =
+      (GstUriDownloader *) (gst_pad_get_element_private (pad));
+
+  switch (event->type) {
+    case GST_EVENT_EOS:{
+      GST_DEBUG_OBJECT (downloader, "Got EOS on the fetcher pad");
+      g_mutex_lock (downloader->priv->lock);
+      if (downloader->priv->download != NULL) {
+        /* signal we have fetched the URI */
+        downloader->priv->download->completed = TRUE;
+        downloader->priv->download->download_stop_time = g_get_real_time ();
+        GST_DEBUG_OBJECT (downloader, "Signaling chain funtion");
+        g_cond_signal (downloader->priv->cond);
+      }
+      g_mutex_unlock (downloader->priv->lock);
+      break;
+    }
+    default:
+      break;
+  }
+
+  gst_event_unref (event);
+  return FALSE;
+}
+
+static GstBusSyncReply
+gst_uri_downloader_bus_handler (GstBus * bus,
+    GstMessage * message, gpointer data)
+{
+  GstUriDownloader *downloader = (GstUriDownloader *) (data);
+
+  if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR ||
+      GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING) {
+    GST_WARNING_OBJECT (downloader,
+        "Received error in bus from the source element, "
+        "the download will be cancelled");
+    /* remove the sync handler to avoid duplicated messages */
+    gst_bus_set_sync_handler (downloader->priv->bus, NULL, NULL);
+    gst_uri_downloader_cancel (downloader);
+  }
+
+  gst_message_unref (message);
+  return GST_BUS_DROP;
+}
+
+static GstFlowReturn
+gst_uri_downloader_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstUriDownloader *downloader =
+      (GstUriDownloader *) gst_pad_get_element_private (pad);
+
+  /* HTML errors (404, 500, etc...) are also pushed through this pad as
+   * response but the source element will also post a warning or error message
+   * in the bus, which is handled synchronously cancelling the download.
+   */
+  g_mutex_lock (downloader->priv->lock);
+  if (downloader->priv->download == NULL) {
+    /* Download cancelled, quit */
+    goto done;
+  }
+
+  GST_LOG_OBJECT (downloader,
+      "The uri fetcher received a new buffer of size %u",
+      GST_BUFFER_SIZE (buf));
+  if (!gst_fragment_add_buffer (downloader->priv->download, buf))
+    GST_WARNING_OBJECT (downloader, "Could not add buffer to fragment");
+
+done:
+  {
+    g_mutex_unlock (downloader->priv->lock);
+    return GST_FLOW_OK;
+  }
+}
+
+static void
+gst_uri_downloader_stop (GstUriDownloader * downloader)
+{
+  GstPad *pad;
+  GST_DEBUG_OBJECT (downloader, "Stopping source element");
+
+  /* remove the bus' sync handler */
+  gst_bus_set_sync_handler (downloader->priv->bus, NULL, NULL);
+  /* unlink the source element from the internal pad */
+  pad = gst_pad_get_peer (downloader->priv->pad);
+  if (pad) {
+    gst_pad_unlink (pad, downloader->priv->pad);
+    gst_object_unref (pad);
+  }
+  /* set the element state to NULL */
+  if (downloader->priv->urisrc)
+  {
+    gst_element_set_state (downloader->priv->urisrc, GST_STATE_NULL);
+    gst_element_get_state (downloader->priv->urisrc, NULL, NULL,
+        GST_CLOCK_TIME_NONE);
+  }
+}
+
+void
+gst_uri_downloader_cancel (GstUriDownloader * downloader)
+{
+  g_mutex_lock (downloader->priv->lock);
+  if (downloader->priv->download != NULL) {
+    GST_DEBUG_OBJECT (downloader, "Cancelling download");
+    g_object_unref (downloader->priv->download);
+    downloader->priv->download = NULL;
+  } else {
+    GST_DEBUG_OBJECT (downloader,
+        "Trying to cancell a download that was alredy cancelled");
+  }
+
+  GST_DEBUG_OBJECT (downloader, "Signaling chain funtion");
+  downloader->priv->canceled = TRUE;
+  g_cond_signal (downloader->priv->cond);
+  g_mutex_unlock (downloader->priv->lock);
+}
+
+static gboolean
+gst_uri_downloader_set_uri (GstUriDownloader * downloader, const gchar * uri)
+{
+  GstPad *pad;
+
+  if (!gst_uri_is_valid (uri))
+    return FALSE;
+
+  if (downloader->priv->urisrc == NULL) {
+    GST_DEBUG_OBJECT (downloader, "Creating source element for the URI:%s", uri);
+    downloader->priv->urisrc = gst_element_make_from_uri (GST_URI_SRC, uri, NULL);
+    if (!downloader->priv->urisrc)
+      return FALSE;
+  } else {
+    GST_DEBUG_OBJECT (downloader, "Reusing existing source element for the URI:%s", uri);
+    if (!gst_uri_handler_set_uri (GST_URI_HANDLER (downloader->priv->urisrc), uri))
+      return FALSE;
+  }
+  g_object_set(downloader->priv->urisrc,"ahs-streaming", TRUE,NULL);
+
+  /* add a sync handler for the bus messages to detect errors in the download */
+  gst_element_set_bus (GST_ELEMENT (downloader->priv->urisrc),
+      downloader->priv->bus);
+  gst_bus_set_sync_handler (downloader->priv->bus,
+      gst_uri_downloader_bus_handler, downloader);
+
+  pad = gst_element_get_static_pad (downloader->priv->urisrc, "src");
+  if (!pad)
+    return FALSE;
+  gst_pad_link (pad, downloader->priv->pad);
+  gst_object_unref (pad);
+  return TRUE;
+}
+
+GstFragment *
+gst_uri_downloader_fetch_uri (GstUriDownloader * downloader, const gchar * uri)
+{
+  GstStateChangeReturn ret;
+  GstFragment *download = NULL;
+/* add setting UA,cookies */
+  gchar **cookies;
+
+  g_mutex_lock (downloader->priv->lock);
+
+  if(downloader->priv->canceled) {
+    GST_DEBUG_OBJECT (downloader, "Uridownloader was canceled.");
+    goto quit;
+  }
+
+  if (!gst_uri_downloader_set_uri (downloader, uri)) {
+    goto quit;
+  }
+
+  /* add setting UA,cookies */
+  g_object_set (downloader->priv->urisrc, "cookies", downloader->priv->cookies, NULL);
+  g_object_set (downloader->priv->urisrc, "user-agent", downloader->priv->user_agent, NULL);
+
+  downloader->priv->download = gst_fragment_new ();
+
+  ret = gst_element_set_state (downloader->priv->urisrc, GST_STATE_PLAYING);
+  if (ret == GST_STATE_CHANGE_FAILURE) {
+    g_object_unref (downloader->priv->download);
+    downloader->priv->download = NULL;
+    goto quit;
+  }
+
+  /* wait until:
+   *   - the download succeed (EOS in the src pad)
+   *   - the download failed (Error message on the fetcher bus)
+   *   - the download was canceled
+   */
+  GST_DEBUG_OBJECT (downloader, "Waiting to fetch the URI");
+  g_cond_wait (downloader->priv->cond, downloader->priv->lock);
+
+/* add setting UA,cookies */
+  g_object_get (downloader->priv->urisrc, "cookies", &cookies, NULL);
+  gst_uri_downloader_set_cookies (downloader, cookies);
+
+  download = downloader->priv->download;
+  downloader->priv->download = NULL;
+
+  if (download != NULL)
+    GST_INFO_OBJECT (downloader, "URI fetched successfully");
+  else
+    GST_INFO_OBJECT (downloader, "Error fetching URI");
+
+quit:
+  {
+    g_mutex_unlock (downloader->priv->lock);
+    gst_uri_downloader_stop (downloader);
+    return download;
+  }
+}
+
+/* add setting UA,cookies */
+void
+gst_uri_downloader_set_user_agent (GstUriDownloader * downloader, gchar * user_agent)
+{
+  if (downloader->priv->user_agent)
+    g_free (downloader->priv->user_agent);
+
+  downloader->priv->user_agent = user_agent;
+}
+
+void
+gst_uri_downloader_set_cookies (GstUriDownloader * downloader, gchar ** cookies)
+{
+  if (downloader->priv->cookies)
+    g_strfreev (downloader->priv->cookies);
+
+  downloader->priv->cookies = cookies;
+}
diff --git a/dashdemux/src/gsturidownloader.h b/dashdemux/src/gsturidownloader.h
new file mode 100755 (executable)
index 0000000..b2b5f06
--- /dev/null
@@ -0,0 +1,66 @@
+/* GStreamer
+ * Copyright (C) 2011 Andoni Morales Alastruey <ylatuya@gmail.com>
+ *
+ * gsturidownloader.h:
+ *
+ * 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.
+ *
+ * Youshould 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 __GSTURI_DOWNLOADER_H__
+#define __GSTURI_DOWNLOADER_H__
+
+#include <glib-object.h>
+#include <gst/gst.h>
+#include "gstfragment.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_URI_DOWNLOADER (gst_uri_downloader_get_type())
+#define GST_URI_DOWNLOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_URI_DOWNLOADER,GstUriDownloader))
+#define GST_URI_DOWNLOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_URI_DOWNLOADER,GstUriDownloaderClass))
+#define GST_IS_URI_DOWNLOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_URI_DOWNLOADER))
+#define GST_IS_URI_DOWNLOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_URI_DOWNLOADER))
+
+typedef struct _GstUriDownloader GstUriDownloader;
+typedef struct _GstUriDownloaderPrivate GstUriDownloaderPrivate;
+typedef struct _GstUriDownloaderClass GstUriDownloaderClass;
+
+struct _GstUriDownloader
+{
+  GstObject parent;
+
+  GstUriDownloaderPrivate *priv;
+};
+
+struct _GstUriDownloaderClass
+{
+  GstObjectClass parent_class;
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+GType gst_uri_downloader_get_type (void);
+
+GstUriDownloader * gst_uri_downloader_new (void);
+GstFragment * gst_uri_downloader_fetch_uri (GstUriDownloader * downloader, const gchar * uri);
+void gst_uri_downloader_cancel (GstUriDownloader *downloader);
+/* add setting UA,cookies */
+void gst_uri_downloader_set_user_agent (GstUriDownloader * downloader, gchar * user_agent);
+void gst_uri_downloader_set_cookies (GstUriDownloader * downloader, gchar ** cookies);
+void gst_uri_downloader_reset(GstUriDownloader *downloader);
+G_END_DECLS
+#endif /* __GSTURIDOWNLOADER_H__ */
diff --git a/debian/changelog b/debian/changelog
new file mode 100755 (executable)
index 0000000..3a3a820
--- /dev/null
@@ -0,0 +1,272 @@
+gst-plugins-ext0.10 (0.2.22-0) unstable; urgency=low
+
+  * [encodebin] Add error log for element link failure
+  * Tag: gst-plugins-ext0.10_0.2.22-0
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Sat, 02 Feb 2013 14:07:59 +0900
+
+gst-plugins-ext0.10 (0.2.21-0) unstable; urgency=low
+
+  * [evasimagesink] enhance code for setting a new evas image object during playing
+  * Tag: gst-plugins-ext0.10_0.2.21-0
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Tue, 15 Jan 2013 21:24:33 +0900
+
+gst-plugins-ext0.10 (0.2.19-2) unstable; urgency=low
+
+  * [evasimagesink] add defense code to avoid seg.fault
+  * Tag: gst-plugins-ext0.10_0.2.19-2
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Mon, 07 Jan 2013 22:55:11 +0900
+
+gst-plugins-ext0.10 (0.2.16-0) unstable; urgency=low
+
+  * Fix prevent issue
+  * Tag: gst-plugins-ext0.10_0.2.16-0
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Sat, 22 Dec 2012 14:53:41 +0900
+
+gst-plugins-ext0.10 (0.2.15-0) unstable; urgency=low
+
+  * [evasimagesink] fix prevent defects
+  * Git: framework/multimedia/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.15-0
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Sat, 22 Dec 2012 14:03:42 +0900
+
+gst-plugins-ext0.10 (0.2.14-0) unstable; urgency=low
+
+  * Solving Prevent issues.
+  * Git: framework/multimedia/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.14-0
+
+ -- Abhishek Bajaj <abhi.bajaj@samsung.com>  Fri, 21 Dec 2012 15:30:27 +0530
+
+gst-plugins-ext0.10 (0.2.12-0) unstable; urgency=low
+
+  * drm_trusted was changed.
+  * Git: framework/multimedia/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.12-0
+
+ -- Haejeong Kim <backto.kim@samsung.com>  Thu, 06 Dec 2012 14:34:27 +0900
+
+gst-plugins-ext0.10 (0.2.9-0) unstable; urgency=low
+
+  * [evasimagesink] modify present_data_addr, not using vir_addr
+  * Git: framework/multimedia/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.9-0
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Tue, 16 Oct 2012 18:37:08 +0900
+
+gst-plugins-ext0.10 (0.2.8-1) unstable; urgency=low
+
+  * add default smack manifest
+  * Git: framework/multimedia/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.8-1
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Fri, 21 Sep 2012 11:27:42 +0900
+
+gst-plugins-ext0.10 (0.2.5-0) unstable; urgency=low
+
+  * [encodebin] Add new property to select video converting element
+  * Git: gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.5-0
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 13 Sep 2012 15:26:46 +0900
+
+gst-plugins-ext0.10 (0.2.4-0) unstable; urgency=low
+
+  * [avsysmemsink] change sink pad's capabilities to bgra8888
+  * Git: framework/multimedia/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.4-0
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Thu, 06 Sep 2012 22:23:15 +0900
+
+gst-plugins-ext0.10 (0.2.3-0) unstable; urgency=low
+
+  * [evasimagesink] fix code to show frame if evas image object does not support gl zerocopy
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.3-0
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Mon, 09 Jul 2012 16:26:40 +0900
+
+gst-plugins-ext0.10 (0.2.2-0) unstable; urgency=low
+
+  * [evasimagesink] add evas_object_event_callback_del() for EVAS_CALLBACK_DEL and EVAS_CALLBACK_RESIZE event
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.2-0
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Mon, 18 Jun 2012 14:19:04 +0900
+
+gst-plugins-ext0.10 (0.2.1-0) unstable; urgency=low
+
+  * [evasimagesink] 1.handling GST_EVENT_CUSTOM_DOWNSTREAM_OOB event to skip memory copy in ecore pipe callback  2.remove redundancy ecore_pipe_del() 3.add evas image object resize callback
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.1-0
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Tue, 05 Jun 2012 12:03:39 +0900
+
+gst-plugins-ext0.10 (0.2.0-1) unstable; urgency=low
+
+  * Apply new drm
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.0-1
+
+ -- Seungbae Shin <seungbae.shin@samsung.com>  Wed, 23 May 2012 11:59:22 +0900
+
+gst-plugins-ext0.10 (0.2.0-0) unstable; urgency=low
+
+  * [AudioRoute] remove sound path in avsysaudiosink
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.2.0-0
+
+ -- Seungbae Shin <seungbae.shin@samsung.com>  Mon, 23 Apr 2012 14:10:06 +0900
+
+gst-plugins-ext0.10 (0.1.10-1) unstable; urgency=low
+
+  * Enable trickplay audio in case of rate > 0
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.10-1
+
+ -- Dowan Kim <dowan2171.kim@samsung.com>  Tue, 24 Apr 2012 14:44:26 +0900
+
+gst-plugins-ext0.10 (0.1.10-0) unstable; urgency=low
+
+  * [evasimagesink] 1. enhance code for multi-instance usage  2. apply MMTA for time analysis
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.10-0
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Thu, 19 Apr 2012 19:35:13 +0900
+
+gst-plugins-ext0.10 (0.1.9-0) unstable; urgency=low
+
+  * [avsysmemsink] update caps format
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.9-0
+
+ -- Younghwan Ahn <younghwan_.an@samsung.com>  Mon, 02 Apr 2012 19:03:39 +0900
+
+gst-plugins-ext0.10 (0.1.8-0) unstable; urgency=low
+
+  * Audiotp plugin added
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.8-0
+
+ -- Santhoshi.KS <santhoshi.ks@samsung.com>  Fri, 2 Mar 2012 18:52:26 +0900
+
+gst-plugins-ext0.10 (0.1.7-0) unstable; urgency=low
+
+  * [avsysaudiosink] remove memcpy when pcm write
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.7-0
+
+ -- Seungbae Shin <seungbae.shin@samsung.com>  Mon, 13 Feb 2012 13:24:37 +0900
+
+gst-plugins-ext0.10 (0.1.6-0) unstable; urgency=low
+
+  * [evasimagesink] 1. add visible property  2. add GST_DEBUG log  3. code cleanup
+  * [avsystem] revise a parameter of g_signal_emit() in gstavsysmemsink.c
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.6-0
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Wed, 08 Feb 2012 14:34:10 +0900
+
+gst-plugins-ext0.10 (0.1.5-1) unstable; urgency=low
+
+  * Remove unused build dependency
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.5-1
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Tue, 20 Dec 2011 16:26:58 +0900
+
+gst-plugins-ext0.10 (0.1.5-0) unstable; urgency=low
+
+  * Remove avsysvideosrc plugin, gettext related and unused files
+  * Change license from Apache-2.0 to LGPL
+  * Git: slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.5-0
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Tue, 20 Dec 2011 14:41:14 +0900
+
+gst-plugins-ext0.10 (0.1.4-2) unstable; urgency=low
+
+  * Add missing files : gettext.h gst-i18n-lib.h for drmsrc
+  * Git: slp-source.sec.samsung.net:slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.4-2
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Wed, 07 Dec 2011 13:55:23 +0900
+
+gst-plugins-ext0.10 (0.1.4-1) unstable; urgency=low
+
+  * Replace boilerplate - APACHE v2.0
+  * Delete unused files : gstavsysvideosink, encodetest, gstpreviewbin
+  * Git: slp-source.sec.samsung.net:slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.4-1
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Fri, 02 Dec 2011 14:43:21 +0900
+
+gst-plugins-ext0.10 (0.1.4-0) unstable; urgency=low
+
+  * [avsysaudiosrc] remove audio-route property
+  * [pdpushsrc] fix Makefile.am
+  * Git: slp-source.sec.samsung.net:slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.4-0
+
+ -- Seungbae Shin <seungbae.shin@samsung.com>  Mon, 31 Oct 2011 18:15:01 +0900
+
+gst-plugins-ext0.10 (0.1.3-1) unstable; urgency=low
+
+  * [pdpushsrc] initial version
+  * Git: slp-source.sec.samsung.net:slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.3-1
+
+ -- Younghwan Ahn <younghwan_.an@samsung.com>  Mon, 24 Oct 2011 12:51:49 +0900
+
+gst-plugins-ext0.10 (0.1.3-0) unstable; urgency=low
+
+  * 1. [avsysaudiosink] restore sound path according to current policy
+  * 2. [avsysaudiosink] remove unused function/variables
+  * Git: slp-source.sec.samsung.net:slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.3-0
+
+ -- Seungbae Shin <seungbae.shin@samsung.com>  Thu, 20 Oct 2011 18:03:39 +0900
+
+gst-plugins-ext0.10 (0.1.2-1) unstable; urgency=low
+
+  * Fix bugs resulted from prevent test (delete unnecessary compare codes and add preventing memory leak codes)
+  * Git: slp-source.sec.samsung.net:slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.2-1
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Tue, 11 Oct 2011 15:50:08 +0900
+
+gst-plugins-ext0.10 (0.1.2-0) unstable; urgency=low
+
+  * [avsysvideosrc] Update code for metadata of samsung extension format
+  * Git: slp-source.sec.samsung.net:slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.2-0
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Tue, 11 Oct 2011 15:39:10 +0900
+
+gst-plugins-ext0.10 (0.1.1-2) unstable; urgency=low
+
+  * [evasimagesink] Fix BS on U1 - add defensive code for gl extension error
+  * Git: slp-source.sec.samsung.net:slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.1-2
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 06 Oct 2011 20:14:01 +0900
+
+gst-plugins-ext0.10 (0.1.1-1) unstable; urgency=low
+
+  * [avsysvideosrc] Correct thumbnail size when JPEG capture
+  * Git: slp-source.sec.samsung.net:slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.1-1
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Mon, 26 Sep 2011 15:27:25 +0900
+
+gst-plugins-ext0.10 (0.1.1-0) unstable; urgency=low
+
+  * Initial Release.
+  * Git: slp-source.sec.samsung.net:slp/pkgs/g/gst-plugins-ext0.10
+  * Tag: gst-plugins-ext0.10_0.1.1-0
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Wed, 24 Aug 2011 09:58:05 +0900
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100755 (executable)
index 0000000..e4ad9dc
--- /dev/null
@@ -0,0 +1,18 @@
+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>, Santhoshi KS <santhoshi.ks@samsung.com>
+Build-Depends: debhelper (>= 5), libgstreamer0.10-dev, libgstreamer-plugins-base0.10-dev, libavsystem-dev, libmm-ta-dev, drm-client-dev, drm-trusted-dev, libecore-dev, libevas-dev, libmm-ta-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-client-0, drm-trusted-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
new file mode 100644 (file)
index 0000000..bd79a0c
--- /dev/null
@@ -0,0 +1,16 @@
+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
new file mode 100644 (file)
index 0000000..f93192c
--- /dev/null
@@ -0,0 +1,9 @@
+@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
+@PREFIX@/lib/gstreamer-0.10/libgstaudiotp.so
+@PREFIX@/lib/gstreamer-0.10/libgstaudioeq.so
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..49e5ea4
--- /dev/null
@@ -0,0 +1,128 @@
+#!/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 37eb3bb..cd3f88b 100755 (executable)
@@ -14,14 +14,14 @@ plugin_LTLIBRARIES = libgstdrmsrc.la
 ##############################################################################
 
 # sources used to compile this plug-in
-libgstdrmsrc_la_SOURCES = gstdrmsrc.c
+libgstdrmsrc_la_SOURCES = gstdrmsrc.c drm_util.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_CFLAGS = $(GST_CFLAGS) $(DRM_CLIENT_CFLAGS) $(DRM_TRUSTED_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+libgstdrmsrc_la_LIBADD = $(GST_LIBS) $(DRM_CLIENT_LIBS) $(DRM_TRUSTED_LIBS) $(GST_BASE_LIBS) 
 libgstdrmsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
 # headers we need but don't want installed
-noinst_HEADERS = gstdrmsrc.h
+noinst_HEADERS = gstdrmsrc.h drm_util.h
 
diff --git a/drmsrc/src/drm_util.c b/drmsrc/src/drm_util.c
new file mode 100755 (executable)
index 0000000..dcff886
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * drm-util.c
+ *
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Seungbae Shin <seungbae.shin@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
+ *
+ */
+#include <string.h>
+#include <drm_trusted_client.h>
+#include "drm_util.h"
+
+gboolean drm_util_open (DRM_DECRYPT_HANDLE *phandle, char* file_path, int file_type)
+{
+       drm_trusted_result_e drm_trusted_result;
+       drm_trusted_open_decrypt_info_s open_decrypt_info;
+       drm_trusted_open_decrypt_resp_data_s open_decrypt_resp;
+       drm_trusted_set_consumption_state_info_s decrypt_state_data = { DRM_CONSUMPTION_STARTED };
+
+       if (phandle == NULL || file_path == NULL) {
+               GST_ERROR ("Invalid parameter, phandle=%p, file_path=%p", phandle, file_path);
+               return FALSE;
+       }
+
+       /* Fill parameter structure for opening decrypt session */
+       memset (&open_decrypt_info, 0, sizeof (drm_trusted_open_decrypt_info_s));
+       memset (&open_decrypt_resp, 0, sizeof (drm_trusted_open_decrypt_resp_data_s));
+
+       strncpy (open_decrypt_info.filePath, file_path, sizeof (open_decrypt_info.filePath)-1);
+       open_decrypt_info.file_type = file_type;
+       open_decrypt_info.permission = DRM_TRUSTED_PERMISSION_TYPE_PLAY;
+
+       /* Open decrypt session */
+       drm_trusted_result = drm_trusted_open_decrypt_session(&open_decrypt_info, &open_decrypt_resp, phandle);
+       if (drm_trusted_result != DRM_TRUSTED_RETURN_SUCCESS || *phandle == NULL) {
+               GST_ERROR ("Error in drm_trusted_open_decrypt_session(), error=%x, *phandle=%p,", drm_trusted_result, *phandle);
+               return FALSE;
+       }
+       GST_DEBUG ("drm_trusted_open_decrypt_session () success!!, ret=%x, *phandle=%p", drm_trusted_result, *phandle);
+
+       /* Set decryption state to STARTED */
+       drm_trusted_result = drm_trusted_set_decrypt_state(*phandle, &decrypt_state_data);
+       if (drm_trusted_result != DRM_TRUSTED_RETURN_SUCCESS) {
+               GST_ERROR ("Error in drm_trusted_set_decrypt_state(), error=%x", drm_trusted_result);
+               drm_trusted_close_decrypt_session (phandle);
+               *phandle = NULL;
+               return FALSE;
+       }
+       GST_DEBUG ("drm_trusted_set_decrypt_state () success!!, ret=%x, *phandle=%p", drm_trusted_result, *phandle);
+
+       return TRUE;
+}
+
+gboolean drm_util_read (DRM_DECRYPT_HANDLE handle, unsigned char* buf, unsigned int buf_length, unsigned int *read_size)
+{
+       drm_trusted_result_e drm_trusted_result;
+       drm_trusted_payload_info_s payload_info;
+       drm_trusted_read_decrypt_resp_data_s decrypt_resp;
+
+       if (handle == NULL || buf == NULL) {
+               GST_ERROR ("Invalid parameter, handle=%p, buf=%p", handle, buf);
+               return FALSE;
+       }
+
+       GST_DEBUG ("Enter [%s] buf=%p, length=%d, read_size=%p", __func__, buf, buf_length, read_size);
+
+       /* fill input/output data */
+       memset (&payload_info, 0, sizeof (drm_trusted_payload_info_s));
+       memset (&decrypt_resp, 0, sizeof (drm_trusted_read_decrypt_resp_data_s));
+
+       payload_info.payload_data = buf;
+       payload_info.payload_data_len = buf_length;
+       payload_info.payload_data_output = buf;
+
+       drm_trusted_result = drm_trusted_read_decrypt_session (handle, &payload_info, &decrypt_resp);
+       if(drm_trusted_result != DRM_TRUSTED_RETURN_SUCCESS) {
+               GST_ERROR ("Error in drm_trusted_read_decrypt_session() [%x]", drm_trusted_result);
+               return FALSE;
+       }
+
+       GST_DEBUG ("Leave [%s], drm_trusted_read_decrypt_session() success, requested=%d, read_size=%d", __func__, buf_length, decrypt_resp.read_size);
+       if (read_size)
+               *read_size = decrypt_resp.read_size;
+
+       return TRUE;
+}
+
+gboolean drm_util_seek (DRM_DECRYPT_HANDLE handle, int offset, int mode)
+{
+       drm_trusted_result_e drm_trusted_result;
+       drm_trusted_seek_decrypt_info_s seek_decrypt_info;
+       memset (&seek_decrypt_info, 0, sizeof(drm_trusted_seek_decrypt_info_s));
+
+       GST_DEBUG ("Enter [%s] offset=%d, mode=%d", __func__, offset, mode);
+
+       seek_decrypt_info.offset = offset;
+       seek_decrypt_info.seek_mode = mode;
+
+       drm_trusted_result = drm_trusted_seek_decrypt_session(handle, &seek_decrypt_info);
+       if (drm_trusted_result != DRM_TRUSTED_RETURN_SUCCESS) {
+               GST_ERROR ("Error in drm_trusted_seek_decrypt_session(), error=%x", drm_trusted_result);
+               return FALSE;
+       }
+
+       GST_DEBUG ("Leave [%s], drm_trusted_seek_decrypt_session () success!!", __func__);
+       return TRUE;
+}
+
+gboolean drm_util_tell (DRM_DECRYPT_HANDLE handle, unsigned int *offset)
+{
+       drm_trusted_result_e drm_trusted_result;
+       drm_trusted_tell_decrypt_resp_data_s tell_decrypt_resp_data;
+
+       if (handle == NULL || offset == NULL) {
+               GST_ERROR ("Invalid parameter, handle=%p, offset=%p", handle, offset);
+               return FALSE;
+       }
+
+       GST_DEBUG ("Enter [%s] offset=%p", __func__, offset);
+
+       memset (&tell_decrypt_resp_data, 0, sizeof(drm_trusted_tell_decrypt_resp_data_s));
+
+       drm_trusted_result = drm_trusted_tell_decrypt_session(handle, &tell_decrypt_resp_data);
+       if (drm_trusted_result != DRM_TRUSTED_RETURN_SUCCESS) {
+               GST_ERROR ("Error in drm_trusted_tell_decrypt_session(), error=%x", drm_trusted_result);
+               return FALSE;
+       }
+
+       if (offset)
+               *offset = tell_decrypt_resp_data.offset;
+
+       GST_DEBUG ("Leave [%s], drm_trusted_tell_decrypt_session () success!!", __func__);
+
+       return TRUE;
+}
+
+gboolean drm_util_close (DRM_DECRYPT_HANDLE *phandle)
+{
+       drm_trusted_result_e drm_trusted_result;
+       drm_trusted_set_consumption_state_info_s decrypt_state_data = { DRM_CONSUMPTION_STOPPED };
+
+       if (phandle == NULL) {
+               GST_ERROR ("Invalid parameter, phandle=%p", phandle);
+               return FALSE;
+       }
+
+       /* Set decryption state to STOPPED */
+       drm_trusted_result = drm_trusted_set_decrypt_state(*phandle, &decrypt_state_data);
+       if (drm_trusted_result != DRM_TRUSTED_RETURN_SUCCESS) {
+               GST_ERROR ("Error in drm_trusted_set_decrypt_state(), error=%x", drm_trusted_result);
+       } else {
+               GST_DEBUG ("drm_trusted_set_decrypt_state () success!!");
+       }
+
+       /* Close decrypt session */
+       drm_trusted_result = drm_trusted_close_decrypt_session(phandle);
+       if(drm_trusted_result != DRM_TRUSTED_RETURN_SUCCESS) {
+               GST_ERROR ("Error in drm_trusted_close_decrypt_session() error=%x", drm_trusted_result);
+               return FALSE;
+       }
+       GST_DEBUG ("drm_trusted_close_decrypt_session() success!!!");
+
+       return TRUE;
+}
diff --git a/drmsrc/src/drm_util.h b/drmsrc/src/drm_util.h
new file mode 100755 (executable)
index 0000000..2e7487d
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * drm_util.h
+ *
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Seungbae Shin <seungbae.shin@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 __DRM_UTIL_H__
+#define __DRM_UTIL_H__
+
+#include <gst/gst.h>
+
+#include <drm_trusted_client_types.h>
+
+gboolean drm_util_open (DRM_DECRYPT_HANDLE *phandle, char* file_path, int file_type);
+gboolean drm_util_read (DRM_DECRYPT_HANDLE handle, unsigned char* buf, unsigned int buf_length, unsigned int *read_size);
+gboolean drm_util_seek (DRM_DECRYPT_HANDLE handle, int offset, int mode);
+gboolean drm_util_tell (DRM_DECRYPT_HANDLE handle, unsigned int *offset);
+gboolean drm_util_close (DRM_DECRYPT_HANDLE *phandle);
+
+#endif /* __DRM_UTIL_H__ */
index 5e2776d..74bf4d2 100755 (executable)
 #endif
 #include "gstdrmsrc.h"
 
+#include "drm_util.h"
+#include <drm_client.h>
+#include <drm_client_types.h>
+
+#ifdef CONTROL_PAGECACHE
+#include <fcntl.h>
+#define DEFAULT_DO_FADVISE_THRESHOLD    (100 * 1024 * 1024)    /* 100 MB */
+#endif
+
 #define LOG_TRACE(message)  //g_print("DRM_SRC: %s: %d: %s - %s \n", __FILE__, __LINE__, __FUNCTION__, message);
 
 #define GST_TAG_PLAYREADY "playready_file_path"
 
 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,GST_STATIC_CAPS_ANY);
 
+#ifdef CONTROL_PAGECACHE
+#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
+#define DRMSRC_FADVISE_DONT(x_fd, x_offset, x_length) \
+       do \
+       { \
+               if (posix_fadvise64(x_fd, x_offset, x_length, POSIX_FADV_DONTNEED) != 0) \
+               { \
+                       GST_ERROR("Set posix_fadvise with POSIX_FADV_DONTNEED failed"); \
+               } \
+       }while (0);
+#else
+#define DRMSRC_FADVISE_DONT(x_fd, x_offset, x_length) \
+       do \
+       { \
+               if (posix_fadvise(x_fd, x_offset, x_length, POSIX_FADV_DONTNEED) != 0) \
+               { \
+                       GST_ERROR("Set posix_fadvise with POSIX_FADV_DONTNEED failed"); \
+               } \
+       }while (0);
+#endif
+#endif
 
 GST_DEBUG_CATEGORY_STATIC (gst_drm_src_debug);
 #define GST_CAT_DEFAULT gst_drm_src_debug
 
 enum
 {
-       ARG_0,
-       ARG_LOCATION,
-       ARG_FD
+  ARG_0,
+  ARG_LOCATION,
+  ARG_FD,
+  IS_DRM
 };
 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);
@@ -51,7 +82,9 @@ 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);
-
+static gboolean gst_drm_src_query (GstBaseSrc * src, GstQuery * query);
+static GstStateChangeReturn gst_drm_src_change_state (GstElement * element,
+    GstStateChange transition);
 /**
  * This function does the following:
  *  1. Initializes GstDrmSrc ( defines gst_drm_get_type)
@@ -62,15 +95,15 @@ static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
  */
 static void _do_init (GType drmsrc_type)
 {
-       // 1. Initializes GstDrmSrc ( defines gst_drm_get_type)
-       static const GInterfaceInfo urihandler_info = {
-               gst_drm_src_uri_handler_init,
-               NULL,
-               NULL
-       };
-
-       g_type_add_interface_static (drmsrc_type, GST_TYPE_URI_HANDLER, &urihandler_info);
-       GST_DEBUG_CATEGORY_INIT (gst_drm_src_debug, "drmsrc", 0, "drmsrc element");
+  // 1. Initializes GstDrmSrc ( defines gst_drm_get_type)
+  static const GInterfaceInfo urihandler_info = {
+    gst_drm_src_uri_handler_init,
+    NULL,
+    NULL
+  };
+
+  g_type_add_interface_static (drmsrc_type, GST_TYPE_URI_HANDLER, &urihandler_info);
+  GST_DEBUG_CATEGORY_INIT (gst_drm_src_debug, "drmsrc", 0, "drmsrc element");
 }
 GST_BOILERPLATE_FULL (GstDrmSrc, gst_drm_src, GstBaseSrc, GST_TYPE_BASE_SRC,   _do_init);
 /**
@@ -84,15 +117,17 @@ GST_BOILERPLATE_FULL (GstDrmSrc, gst_drm_src, GstBaseSrc, GST_TYPE_BASE_SRC,   _
  */
 static void gst_drm_src_base_init (gpointer g_class)
 {
-       GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-       // 1. Sets the class details
-       gst_element_class_set_details_simple (gstelement_class,
-               "DRM Source",
-               "Source/File",
-               "Read from arbitrary point in a standard/DRM file",
-               "Kishore Arepalli  <kishore.a@samsung.com> and Sadanand Dodawadakar <sadanand.d@samsung.com>");
-      // 2. Adds the source pad template
-       gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&srctemplate));
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+  /*Sets the class details */
+  gst_element_class_set_details_simple (gstelement_class,
+    "DRM Source",
+    "Source/File",
+    "Read from arbitrary point in a standard/DRM file",
+    "Kishore Arepalli  <kishore.a@samsung.com> and Sadanand Dodawadakar <sadanand.d@samsung.com>");
+
+  /*Adds the source pad template */
+  gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&srctemplate));
 }
 /**
  * This function does the following:
@@ -105,38 +140,46 @@ static void gst_drm_src_base_init (gpointer g_class)
  */
 static void gst_drm_src_class_init (GstDrmSrcClass * klass)
 {
-       GObjectClass *gobject_class;
-       GstElementClass *gstelement_class;
-       GstBaseSrcClass *gstbasesrc_class;
-       gobject_class = G_OBJECT_CLASS (klass);
-       gstelement_class = GST_ELEMENT_CLASS (klass);
-       gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
-       // Assigns the function pointers GObject class attributes
-       gobject_class->set_property = gst_drm_src_set_property;
-       gobject_class->get_property = gst_drm_src_get_property;
-       //  1. Installs the properties
-       g_object_class_install_property (gobject_class, ARG_FD,
-               g_param_spec_int ("fd", "File-descriptor",
-               "File-descriptor for the file being mmap()d", 0, G_MAXINT, 0,
-               G_PARAM_READABLE));
-       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));
-
-       // 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);
-       gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_drm_src_stop);
-       gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_drm_src_is_seekable);
-       gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_drm_src_get_size);
-       gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_drm_src_create);
-
-
-       gst_tag_register (GST_TAG_PLAYREADY, GST_TAG_FLAG_META,
-                       G_TYPE_STRING,
-                       "PlayReady File Path",
-                       "a tag that is specific to PlayReady File",
-                       NULL);
+  GObjectClass *gobject_class;
+  GstBaseSrcClass *gstbasesrc_class;
+  gobject_class = G_OBJECT_CLASS (klass);
+  gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
+  GstElementClass *gstelement_class;
+  gstelement_class = (GstElementClass *) klass;
+  /* Assigns the function pointers GObject class attributes */
+  gobject_class->set_property = gst_drm_src_set_property;
+  gobject_class->get_property = gst_drm_src_get_property;
+
+  /* Installs the properties*/
+  g_object_class_install_property (gobject_class, ARG_FD,
+    g_param_spec_int ("fd", "File-descriptor",
+      "File-descriptor for the file being mmap()d", 0, G_MAXINT, 0,
+      G_PARAM_READABLE));
+
+  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_READABLE));
+
+   /*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);
+  gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_drm_src_stop);
+  gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_drm_src_is_seekable);
+  gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_drm_src_get_size);
+  gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_drm_src_create);
+  gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_drm_src_query);
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_drm_src_change_state);
+  gst_tag_register (GST_TAG_PLAYREADY, GST_TAG_FLAG_META,
+    G_TYPE_STRING,
+    "PlayReady File Path",
+    "a tag that is specific to PlayReady File",
+     NULL);
 }
 /**
  * This function does the following:
@@ -149,13 +192,21 @@ static void gst_drm_src_class_init (GstDrmSrcClass * klass)
  */
 static void gst_drm_src_init (GstDrmSrc * src, GstDrmSrcClass * g_class)
 {
-       // 1. Initilizes the parameters of GstDrmSrc
-       src->filename = NULL;
-       src->fd = 0;
-       src->uri = NULL;
-       src->is_regular = FALSE;
-       src->seekable = FALSE;
-       PROFILE_INIT;
+  /* Initilizes the parameters of GstDrmSrc */
+  src->filename = NULL;
+  src->fd = 0;
+  src->uri = NULL;
+  src->is_regular = FALSE;
+  src->is_oma = FALSE;
+  src->seekable = FALSE;
+  src->hfile = NULL;
+  src->event_posted = FALSE;
+  src->is_playready = FALSE;
+  src->is_drm = FALSE;
+  src->isopen = FALSE;
+#ifdef CONTROL_PAGECACHE
+  src->accum = 0;
+#endif
 }
 /**
  * This function does the following:
@@ -168,14 +219,14 @@ static void gst_drm_src_init (GstDrmSrc * src, GstDrmSrcClass * g_class)
  */
 static void gst_drm_src_finalize (GObject * object)
 {
-       GstDrmSrc *src;
-
-       src = GST_DRM_SRC (object);
-       //  1. deallocates the filename and uri
-       g_free (src->filename);
-       g_free (src->uri);
-       // 2. calls the parent class->finalize
-       G_OBJECT_CLASS (parent_class)->finalize (object);
+  GstDrmSrc *src;
+
+  src = GST_DRM_SRC (object);
+  /*. deallocates the filename and uri */
+  g_free (src->filename);
+  g_free (src->uri);
+  /* calls the parent class->finalize */
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 /**
  * This function does the following:
@@ -190,35 +241,50 @@ static void gst_drm_src_finalize (GObject * object)
  */
 static gboolean gst_drm_src_set_location (GstDrmSrc * src, const gchar * location)
 {
-       GstState state;
-
-       GST_OBJECT_LOCK (src);
-       //  1. Checks the state
-       state = GST_STATE (src);
-       if (state != GST_STATE_READY && state != GST_STATE_NULL)
-       {
-               GST_DEBUG_OBJECT (src, "setting location in wrong state");
-               GST_OBJECT_UNLOCK (src);
-               return FALSE;
-       }
-       GST_OBJECT_UNLOCK (src);
-       g_free (src->filename);
-       g_free (src->uri);
-       //  2. Checks the filename
-       if (location == NULL)
-       {
-               src->filename = NULL;
-               src->uri = NULL;
-       }
-       else
-       {
-               // 3. Sets the filename
-               src->filename = g_strdup (location);
-               src->uri = gst_uri_construct ("file", src->filename);
-       }
-       g_object_notify (G_OBJECT (src), "location");
-       gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
-       return TRUE;
+  GstState state;
+
+  GST_OBJECT_LOCK (src);
+
+  /* Checks the state */
+  state = GST_STATE (src);
+  if (state != GST_STATE_READY && state != GST_STATE_NULL) {
+    GST_DEBUG_OBJECT (src, "setting location in wrong state");
+    GST_OBJECT_UNLOCK (src);
+    return FALSE;
+  }
+  GST_OBJECT_UNLOCK (src);
+
+  g_free (src->filename);
+  g_free (src->uri);
+
+  /* Checks the filename */
+  if (location == NULL) {
+    src->filename = NULL;
+    src->uri = NULL;
+  } else {
+    /*. Sets the filename */
+    src->filename = g_strdup (location);
+#if 0
+    /*This below API is changing the filename in case of punctuation marks in filename*/
+    src->uri = gst_filename_to_uri (location, NULL);
+#else
+    src->uri = g_strdup_printf ("%s://%s", "file", src->filename);
+
+    drm_bool_type_e is_drm = DRM_FALSE;
+    if (drm_is_drm_file(src->filename, &is_drm) == DRM_RETURN_SUCCESS) {
+      if (is_drm == DRM_TRUE) {
+       src->is_drm = TRUE;
+      }
+    }
+    GST_DEBUG_OBJECT (src, "is drm : %d", src->is_drm);
+#endif
+    GST_INFO_OBJECT(src, "filename : %s", src->filename);
+    GST_INFO_OBJECT(src, "uri      : %s", src->uri);
+  }
+  g_object_notify (G_OBJECT (src), "location");
+  gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
+
+  return TRUE;
 }
 /**
  * This function does the following:
@@ -233,20 +299,21 @@ static gboolean gst_drm_src_set_location (GstDrmSrc * src, const gchar * locatio
  */
 static void gst_drm_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
 {
-       GstDrmSrc *src;
-
-       g_return_if_fail (GST_IS_DRM_SRC (object));
-       src = GST_DRM_SRC (object);
-       switch (prop_id)
-       {
-               //  1. Sets the location of the file.
-               case ARG_LOCATION:
-                       gst_drm_src_set_location (src, g_value_get_string (value));
-                       break;
-               default:
-                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-                       break;
-       }
+  GstDrmSrc *src;
+
+  g_return_if_fail (GST_IS_DRM_SRC (object));
+
+  src = GST_DRM_SRC (object);
+
+  switch (prop_id) {
+  //  1. Sets the location of the file.
+  case ARG_LOCATION:
+    gst_drm_src_set_location (src, g_value_get_string (value));
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
 }
 /**
  * This function does the following:
@@ -262,26 +329,192 @@ static void gst_drm_src_set_property (GObject * object, guint prop_id, const GVa
  */
 static void gst_drm_src_get_property (GObject * object, guint prop_id, GValue * value,GParamSpec * pspec)
 {
-       GstDrmSrc *src;
-
-       g_return_if_fail (GST_IS_DRM_SRC (object));
-       src = GST_DRM_SRC (object);
-       switch (prop_id)
-       {
-               //  1. Provides the location of the file.
-               case ARG_LOCATION:
-                       g_value_set_string (value, src->filename);
-                       break;
-               // 2. Provides the file descriptor.
-               case ARG_FD:
-                       g_value_set_int (value, src->fd);
-                       break;
-               default:
-                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-                       break;
-       }
+  GstDrmSrc *src;
+
+  g_return_if_fail (GST_IS_DRM_SRC (object));
+  src = GST_DRM_SRC (object);
+  switch (prop_id) {
+    case ARG_LOCATION:
+    g_value_set_string (value, src->filename);
+    break;
+    case ARG_FD:
+    g_value_set_int (value, src->fd);
+    break;
+    case IS_DRM:
+    g_value_set_boolean(value, src->is_drm);
+    break;
+    default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+static GstStateChangeReturn
+gst_drm_src_change_state (GstElement * element, GstStateChange transition)
+{
+
+  GstDrmSrc *src = GST_DRM_SRC (element);
+  GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
+  gboolean ret = FALSE;
+  drm_file_type_e file_type = DRM_TYPE_UNDEFINED;
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:{
+      GST_INFO_OBJECT(src,"change state from NULL to ready");
+      drm_result_e drm_result;
+      drm_result = drm_get_file_type (src->filename, &file_type);
+      if (file_type == DRM_TYPE_OMA_V1) {
+      /* Opens the DRM file if it is DRM */
+        if (!src->isopen) {
+          GST_DEBUG_OBJECT (src, "trying  to open drm util");
+          if (drm_util_open (&src->hfile, src->filename, file_type) == FALSE) {
+            GST_ERROR_OBJECT (src, "failed to open drm util");
+            return FALSE;
+          }
+          src->isopen=TRUE;
+        }
+      }
+    break;
+    }
+    case GST_STATE_CHANGE_READY_TO_PAUSED:{
+      GST_INFO_OBJECT(src,"change state from ready to paused");
+      drm_result_e drm_result;
+      drm_result = drm_get_file_type (src->filename, &file_type);
+      if (file_type == DRM_TYPE_OMA_V1){
+        ret = drm_process_request(DRM_REQUEST_TYPE_CLIENT_CLEAN_UP, NULL, NULL);
+        if (DRM_RETURN_SUCCESS == ret) {
+          GST_INFO("Clean Up successful!!");
+        } else {
+          GST_ERROR("Clean Up Failed!!, ret = 0x%x", ret);
+        }
+        ret = drm_trusted_handle_request(DRM_TRUSTED_REQ_TYPE_CLIENT_CLEAN_UP, NULL, NULL);
+        if (DRM_RETURN_SUCCESS == ret) {
+          GST_INFO("Clean Up successful!!");
+        } else {
+          GST_ERROR("Clean Up Failed!!, ret = 0x%x", ret);
+        }
+      }
+      break;
+    }
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{
+      GST_INFO_OBJECT(src,"change state from paused to playing");
+      break;
+    }
+    default:
+      break;
+  }
+  result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{
+      GST_INFO_OBJECT(src,"change state from playing  to paused");
+      break;
+    }
+    case GST_STATE_CHANGE_PAUSED_TO_READY:{
+      GST_INFO_OBJECT(src,"change state from paused to ready");
+      if (src->hfile) {
+        if (src->isopen)
+          if (drm_util_close(&src->hfile))
+            src->isopen=FALSE;
+            src->hfile = NULL;
+#ifdef CONTROL_PAGECACHE
+           DRMSRC_FADVISE_DONT(src->hfile, 0, 0);
+           src->accum = 0;
+#endif
+      }
+      break;
+    }
+    case GST_STATE_CHANGE_READY_TO_NULL:{
+      GST_INFO_OBJECT(src,"change state from ready to null");
+      break;
+    }
+    default:
+    break;
+
+  }
+  return result;
 }
 
+
+
+
+/**
+ * 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* src, guint64 i_uiOffset, guint length, GstBuffer ** o_pBbuffer)
+{
+  GstBuffer *buf = NULL;
+  unsigned int readSize;
+
+  /* Seeks to the specified position for DRM file. */
+  if (G_UNLIKELY (src->read_position != i_uiOffset)) {
+    if (drm_util_seek (src->hfile, i_uiOffset, DRM_SEEK_SET) == FALSE)
+      goto FAILED;
+
+    src->read_position = i_uiOffset;
+  }
+
+  /* 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;
+  }
+
+  /*. Reads from the file and sets the related params for DRM file. */
+  if (drm_util_read (src->hfile, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf), &readSize) == FALSE)
+    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;
+  }
+
+#ifdef CONTROL_PAGECACHE
+       src->accum += readSize;
+       if (src->accum >= DEFAULT_DO_FADVISE_THRESHOLD) {
+               DRMSRC_FADVISE_DONT(src->hfile, 0, 0);
+               src->accum = 0;
+       }
+#endif
+
+  length = readSize;
+  GST_BUFFER_SIZE (buf) = length;
+  GST_BUFFER_OFFSET (buf) = i_uiOffset;
+  GST_BUFFER_OFFSET_END (buf) = i_uiOffset + length;
+  *o_pBbuffer = buf;
+  src->read_position += length;
+
+  return GST_FLOW_OK;
+
+FAILED:
+{
+  GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
+  return GST_FLOW_ERROR;
+}
+}
 /**
  * This function does the following:
  *  1. Seeks to the specified position.
@@ -297,50 +530,67 @@ static void gst_drm_src_get_property (GObject * object, guint prop_id, GValue *
  */
 static GstFlowReturn gst_drm_src_create_read (GstDrmSrc * src, guint64 offset, guint length, GstBuffer ** buffer)
 {
-       int ret;
-       GstBuffer *buf;
-       // 1. Seeks to the specified position.
-       if (G_UNLIKELY (src->read_position != offset))
-       {
-               off_t res;
-               res = lseek (src->fd, offset, SEEK_SET);
-               if (G_UNLIKELY (res < 0 || res != offset))
-               {
-                       GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
-                       return GST_FLOW_ERROR;
-               }
-               src->read_position = offset;
-       }
-       // 2. Allocates a buffer to push the data
-       buf = gst_buffer_new_and_alloc (length);
-       GST_LOG_OBJECT (src, "Reading %d bytes", length);
-       // 3. Reads from the file and sets the related params
-       ret = read (src->fd, GST_BUFFER_DATA (buf), length);
-       if (G_UNLIKELY (ret < 0))
-       {
-               GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
-               gst_buffer_unref (buf);
-               return GST_FLOW_ERROR;
-       }
-       if (G_UNLIKELY ((guint) ret < length && src->seekable))
-       {
-               GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),("unexpected end of file."));
-               gst_buffer_unref (buf);
-               return GST_FLOW_ERROR;
-       }
-       if (G_UNLIKELY (ret == 0 && length > 0))
-       {
-               GST_DEBUG ("non-regular file hits EOS");
-               gst_buffer_unref (buf);
-               return GST_FLOW_UNEXPECTED;
+  int ret;
+  GstBuffer *buf;
+
+  /* Seeks to the specified position. */
+  if (G_UNLIKELY (src->read_position != offset)) {
+    off_t res;
+    res = lseek (src->fd, offset, SEEK_SET);
+    if (G_UNLIKELY (res < 0 || res != offset)) {
+      GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
+      return GST_FLOW_ERROR;
+    }
+    src->read_position = offset;
+  }
+
+  /* Allocates a buffer to push the data */
+  buf = gst_buffer_new_and_alloc (length);
+  if (NULL == buf) {
+    GST_ERROR_OBJECT (src, "failed to allocate memory..");
+    GST_ELEMENT_ERROR (src, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+    return GST_FLOW_ERROR;
+  }
+
+  GST_LOG_OBJECT (src, "Reading %d bytes", length);
+
+  /*  Reads from the file and sets the related params */
+  ret = read (src->fd, GST_BUFFER_DATA (buf), length);
+  if (G_UNLIKELY (ret < 0)) {
+    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
+  }
+
+  if (G_UNLIKELY ((guint) ret < length && src->seekable)) {
+    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),("unexpected end of file."));
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
+  }
+
+  if (G_UNLIKELY (ret == 0 && length > 0)) {
+    GST_DEBUG ("non-regular file hits EOS");
+    gst_buffer_unref (buf);
+    return GST_FLOW_UNEXPECTED;
+  }
+
+#ifdef CONTROL_PAGECACHE
+       src->accum += ret;
+       if (src->accum >= DEFAULT_DO_FADVISE_THRESHOLD) {
+               DRMSRC_FADVISE_DONT(src->fd, 0, 0);
+               src->accum = 0;
        }
-       length = ret;
-       GST_BUFFER_SIZE (buf) = length;
-       GST_BUFFER_OFFSET (buf) = offset;
-       GST_BUFFER_OFFSET_END (buf) = offset + length;
-       *buffer = buf;
-       src->read_position += length;
-       return GST_FLOW_OK;
+       //DRMSRC_FADVISE_DONT(src->fd, offset, ret);
+#endif
+
+  length = ret;
+  GST_BUFFER_SIZE (buf) = length;
+  GST_BUFFER_OFFSET (buf) = offset;
+  GST_BUFFER_OFFSET_END (buf) = offset + length;
+  *buffer = buf;
+  src->read_position += length;
+
+  return GST_FLOW_OK;
 }
 /**
  * This function does the following:
@@ -354,13 +604,73 @@ static GstFlowReturn gst_drm_src_create_read (GstDrmSrc * src, guint64 offset, g
  */
 static GstFlowReturn gst_drm_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer)
 {
-       GstDrmSrc *src = GST_DRM_SRC (basesrc);
+  GstDrmSrc *src = GST_DRM_SRC (basesrc);
 
-       // 1. Calls DRM file read chain method for drm files.
+  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) {
+        if(!gst_pad_push_event (src_pad, gst_event_new_tag (tags))) {
+          GST_ERROR_OBJECT (src, "failed to push tags..");
+          gst_object_unref (src_pad);
+          return GST_FLOW_ERROR;
+        }
+        GST_DEBUG_OBJECT (src, "posting tags returns [%d]", src->event_posted);
+        src->event_posted = TRUE;
+        gst_object_unref (src_pad);
+      }
+    }
+  }
 
-       // 2. Calls normal file read chain method for standard files.
-       return gst_drm_src_create_read (src, offset, length, buffer);
+  if(src->is_oma == TRUE) /* Calls DRM file read chain method for drm files. */
+    return gst_drm_src_create_read_drm_file (src, offset, length, buffer);
+  else /* Calls normal file read chain method for standard files. */
+    return gst_drm_src_create_read (src, offset, length, buffer);
 }
+
+static gboolean
+gst_drm_src_query (GstBaseSrc * basesrc, GstQuery * query)
+{
+  gboolean ret = FALSE;
+  GstDrmSrc *src = GST_DRM_SRC (basesrc);
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_URI:
+      gst_query_set_uri (query, src->uri);
+      ret = TRUE;
+      break;
+    case GST_QUERY_CUSTOM:
+    {
+      GstStructure *s;
+      guint64 size = 0;
+      GValue v = { 0, { { 0 } } };
+      g_value_init(&v, G_TYPE_UINT64);
+
+      s = gst_query_get_structure (query);
+      if (gst_structure_has_name (s, "dynamic-size")) {
+        if (gst_drm_src_get_size (basesrc, &size)){
+          /* succedded. take size */
+          g_value_set_uint64 (&v, size);
+          gst_structure_set_value(s, "size", &v);
+          ret = TRUE;
+        }
+      }
+      break;
+    }
+    default:
+      ret = FALSE;
+      break;
+  }
+
+  if (!ret)
+    ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
+
+  return ret;
+}
+
 /**
  *
  * @param   basesrc    [in]   BaseSrc Structure
@@ -369,8 +679,8 @@ static GstFlowReturn gst_drm_src_create (GstBaseSrc * basesrc, guint64 offset, g
  */
 static gboolean gst_drm_src_is_seekable (GstBaseSrc * basesrc)
 {
-       GstDrmSrc *src = GST_DRM_SRC (basesrc);
-       return src->seekable;
+  GstDrmSrc *src = GST_DRM_SRC (basesrc);
+  return src->seekable;
 }
 /**
  * This function does the following:
@@ -384,22 +694,43 @@ 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 = GST_DRM_SRC (basesrc);
-       unsigned int offset;
+  struct stat stat_results;
+  GstDrmSrc *src = GST_DRM_SRC (basesrc);
+  unsigned int offset;
+
+  /* Gets the filesize for drm file by using seek oprations */
+  if(src->is_oma==TRUE) {
+    drm_util_seek (src->hfile, 0, DRM_SEEK_END);
+    if (drm_util_tell(src->hfile, &offset) == TRUE) {
+      /* FIXME : drm doesn't support 64 */
+      *size = offset;
+    }
+    drm_util_seek (src->hfile, 0, DRM_SEEK_SET);
+    src->read_position = 0;
+    return TRUE;
+  }
+
+  if (!src->seekable) {
+    GST_DEBUG_OBJECT (src, "non-seekable");
+    return FALSE;
+  }
 
-       //  1. Gets the filesize for drm file by using seek oprations
+  /* Gets the file size for standard file by using statistics */
+  if (fstat (src->fd, &stat_results) < 0)
+    return FALSE;
 
-       // 2. Gets the file size for standard file by using statistics
-       if (fstat (src->fd, &stat_results) < 0)
-               return FALSE;
-       *size = stat_results.st_size;
-       return TRUE;
+  *size = stat_results.st_size;
+  GST_DEBUG_OBJECT (src, "size : %"G_GUINT64_FORMAT, *size);
+  return TRUE;
 }
 /**
  * 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
@@ -408,67 +739,107 @@ static gboolean gst_drm_src_get_size (GstBaseSrc * basesrc, guint64 * size)
  */
 static gboolean gst_drm_src_start (GstBaseSrc * basesrc)
 {
-       GstDrmSrc *src = GST_DRM_SRC (basesrc);
-       struct stat stat_results;
-       off_t ret;
-PROFILE_FUNC_BEGIN;
-       // 1. Checks the filename
-       if (src->filename == NULL || src->filename[0] == '\0')
-       {
-               GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,("No file name specified for reading."), (NULL));
-               return FALSE;
-       }
-       // 2. Opens the file and check statistics of the file
-       GST_INFO_OBJECT (src, "opening file %s", src->filename);
-       src->fd = open (src->filename, O_RDONLY | O_BINARY);
-       if (src->fd < 0)
-       {
-               if(errno == ENOENT)
-               {
-                       GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),("No such file \"%s\"", src->filename));
-                       return FALSE;
-               }
-               GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not open file \"%s\" for reading.", src->filename), GST_ERROR_SYSTEM);
-               return FALSE;
-       }
-       if (fstat (src->fd, &stat_results) < 0)
-       {
-               GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not get info on \"%s\".", src->filename), (NULL));
-               close (src->fd);
-               return FALSE;
-       }
-       if (S_ISDIR (stat_results.st_mode))
-       {
-               GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("\"%s\" is a directory.", src->filename), (NULL));
-               close (src->fd);
-               return FALSE;
-       }
-       if (S_ISSOCK (stat_results.st_mode))
-       {
-               GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("File \"%s\" is a socket.", src->filename), (NULL));
-               close (src->fd);
-               return FALSE;
-       }
-       src->read_position = 0;
-
-       // 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 (ret < 0)
-       {
-               GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek "
-                       "failed: %s", g_strerror (errno));
-               src->seekable = FALSE;
-       }
-       else
-       {
-               src->seekable = TRUE;
-       }
-       lseek (src->fd, 0, SEEK_SET);
-       src->seekable = src->seekable && src->is_regular;
-       PROFILE_FUNC_END;
-       return TRUE;
+  GstDrmSrc *src = GST_DRM_SRC (basesrc);
+  struct stat stat_results;
+  drm_result_e drm_result;
+  drm_file_type_e file_type;
+  off_t ret;
+
+  /* Checks the filename */
+  if (src->filename == NULL || src->filename[0] == '\0') {
+    GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,("No file name specified for reading."), (NULL));
+    return FALSE;
+  }
+
+  /*  Opens the file and check statistics of the file */
+  GST_INFO_OBJECT (src, "opening file %s", src->filename);
+  src->fd = open (src->filename, O_RDONLY | O_BINARY);
+  if (src->fd < 0) {
+    if(errno == ENOENT) {
+      GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),("No such file \"%s\"", src->filename));
+      return FALSE;
+    }
+    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not open file \"%s\" for reading.", src->filename), GST_ERROR_SYSTEM);
+    return FALSE;
+  }
+
+  if (fstat (src->fd, &stat_results) < 0) {
+    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not get info on \"%s\".", src->filename), (NULL));
+    close (src->fd);
+    return FALSE;
+  }
+
+  if (S_ISDIR (stat_results.st_mode)) {
+    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("\"%s\" is a directory.", src->filename), (NULL));
+    close (src->fd);
+    return FALSE;
+  }
+
+  if (S_ISSOCK (stat_results.st_mode)) {
+    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("File \"%s\" is a socket.", src->filename), (NULL));
+    close (src->fd);
+    return FALSE;
+  }
+
+  src->read_position = 0;
+
+
+  /* Checks whether DRM file or not.*/
+  drm_result = drm_get_file_type (src->filename, &file_type);
+  if (drm_result != DRM_RETURN_SUCCESS) {
+    GST_ERROR_OBJECT (src,"Error in drm_get_file_type(), error=%d", drm_result);
+    return FALSE;
+  }
+  GST_DEBUG_OBJECT (src, "file_path = [%s], file_type = [%d]", src->filename, file_type);
+
+#if 0
+  if (DRM_TYPE_UNDEFINED != file_type) {
+    drm_bool_type_e is_drm = DRM_FALSE;
+    if (drm_is_drm_file(src->filename, &is_drm) == DRM_RETURN_SUCCESS) {
+      if (is_drm == DRM_TRUE) {
+       src->is_drm = TRUE;
+      }
+    }
+    GST_DEBUG_OBJECT (src, "is drm = [%d]", src->is_drm);
+  }
+#endif
+
+  /* We handles as DRM file if it is drm with OMA type */
+  if (file_type == DRM_TYPE_OMA_V1) { /* FIMXE: what about DRM_TYPE_OMA_V2  */
+    // Gets the DRM_FILE_HANDLE and sets the drm, seekable and regular flags.
+    drm_util_seek (src->hfile, 0, DRM_SEEK_END);
+    drm_util_seek (src->hfile, 0, DRM_SEEK_SET);
+
+    src->seekable      = TRUE;
+    src->is_regular    = TRUE;
+    src->is_oma        = TRUE;
+
+    LOG_TRACE("Exit");
+    return TRUE;
+  }
+
+  if (file_type == DRM_TYPE_PLAYREADY || file_type == DRM_TYPE_PLAYREADY_ENVELOPE) { /* FIXME: what is envelope?? */
+    src->is_playready = TRUE;
+    src->event_posted = FALSE;
+  }
+
+  /* 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 (ret < 0) {
+    GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek failed: %s", g_strerror (errno));
+    src->seekable = FALSE;
+  } else {
+    src->seekable = TRUE;
+  }
+
+  lseek (src->fd, 0, SEEK_SET);
+  src->seekable = src->seekable && src->is_regular;
+
+
+  return TRUE;
 }
 /**
  * This function does the following:
@@ -480,15 +851,22 @@ PROFILE_FUNC_BEGIN;
  */
 static gboolean gst_drm_src_stop (GstBaseSrc * basesrc)
 {
-       GstDrmSrc *src = GST_DRM_SRC (basesrc);
-
-       // 1. Closes the file desciptor and resets the flags
-       if(src->fd > 0)
-               close (src->fd);
-       src->fd = 0;
-       src->is_regular = FALSE;
-//     PROFILE_SHOW_RESULT;
-       return TRUE;
+  GstDrmSrc *src = GST_DRM_SRC (basesrc);
+  // 1. Closes the file desciptor and resets the flags
+  if(src->fd > 0) {
+#ifdef CONTROL_PAGECACHE
+       DRMSRC_FADVISE_DONT(src->fd, 0, 0);
+       src->accum = 0;
+#endif
+    close (src->fd);
+  }
+
+  src->fd = 0;
+  src->is_regular = FALSE;
+  src->event_posted = FALSE;
+  src->is_playready = FALSE;
+
+  return TRUE;
 }
 /**
  *
@@ -499,7 +877,7 @@ static gboolean gst_drm_src_stop (GstBaseSrc * basesrc)
 
 static GstURIType gst_drm_src_uri_get_type (void)
 {
-       return GST_URI_SRC;
+  return GST_URI_SRC;
 }
 
 /**
@@ -513,8 +891,8 @@ static GstURIType gst_drm_src_uri_get_type (void)
 
 static gchar ** gst_drm_src_uri_get_protocols (void)
 {
-       static gchar *protocols[] = { "file", NULL };
-       return protocols;
+  static gchar *protocols[] = { "file", NULL };
+  return protocols;
 }
 /**
  *
@@ -524,8 +902,8 @@ static gchar ** gst_drm_src_uri_get_protocols (void)
  */
 static const gchar * gst_drm_src_uri_get_uri (GstURIHandler *handler)
 {
-       GstDrmSrc *src = GST_DRM_SRC (handler);
-       return src->uri;
+  GstDrmSrc *src = GST_DRM_SRC (handler);
+  return src->uri;
 }
 /**
  * This function does the following:
@@ -540,46 +918,50 @@ static const gchar * gst_drm_src_uri_get_uri (GstURIHandler *handler)
  */
 static gboolean gst_drm_src_uri_set_uri (GstURIHandler *handler, const gchar * uri)
 {
-       gchar *protocol, *location;
-       gboolean ret;
-       GstDrmSrc *src = GST_DRM_SRC (handler);
-       // 1. Checks the protocol
-       protocol = gst_uri_get_protocol (uri);
-       if (strcmp (protocol, "file") != 0)
-       {
-               g_free (protocol);
-               return FALSE;
-       }
-       g_free (protocol);
-       if (g_str_has_prefix (uri, "file://localhost/"))
-       {
-               char *tmp;
-               tmp = g_strconcat ("file://", uri + 16, NULL);
-               location = gst_uri_get_location (tmp);
-               g_free (tmp);
-       }
-       else if (strcmp (uri, "file://") == 0)
-       {
-               gst_drm_src_set_location (src, NULL);
-               return TRUE;
-       }
-       else
-       {
-               location = gst_uri_get_location (uri);
-       }
-       if (!location)
-               return FALSE;
-       // 2. Checks the whether it is absolute or not
-       if (!g_path_is_absolute (location))
-       {
-               g_free (location);
-               return FALSE;
-       }
-       // 3 sets the location
-       ret = gst_drm_src_set_location (src, location);
-       g_free (location);
-       return ret;
+  gchar *location, *hostname = NULL;
+  gboolean ret = FALSE;
+  GstDrmSrc *src = GST_DRM_SRC (handler);
+  GError *error = NULL;
+
+  if (strcmp (uri, "file://") == 0) {
+    /* Special case for "file://" as this is used by some applications
+     *  to test with gst_element_make_from_uri if there's an element
+     *  that supports the URI protocol. */
+    gst_drm_src_set_location (src, NULL);
+    return TRUE;
+  }
+
+  location = g_filename_from_uri (uri, &hostname, &error);
+
+  if (!location || error) {
+    if (error) {
+      GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri,
+          error->message);
+      g_error_free (error);
+    } else {
+      GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc", uri);
+    }
+    goto beach;
+  }
+
+  if ((hostname) && (strcmp (hostname, "localhost"))) {
+    /* Only 'localhost' is permitted */
+    GST_WARNING_OBJECT (src, "Invalid hostname '%s' for filesrc", hostname);
+    goto beach;
+  }
+
+  ret = gst_drm_src_set_location (src, location);
+
+beach:
+  if (location)
+    g_free (location);
+  if (hostname)
+    g_free (hostname);
+
+  return ret;
 }
+
+
 /**
  * This function does the following:
  *  1. Assignes the function pointer for URI related stuff
@@ -591,12 +973,13 @@ static gboolean gst_drm_src_uri_set_uri (GstURIHandler *handler, const gchar * u
  */
 static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
 {
-       GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
-       // 1. Assigning the function pointer for URI related stuff
-       iface->get_type = gst_drm_src_uri_get_type;
-       iface->get_protocols = gst_drm_src_uri_get_protocols;
-       iface->get_uri = gst_drm_src_uri_get_uri;
-       iface->set_uri = gst_drm_src_uri_set_uri;
+  GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
+
+  /* Assigning the function pointer for URI related stuff */
+  iface->get_type = gst_drm_src_uri_get_type;
+  iface->get_protocols = gst_drm_src_uri_get_protocols;
+  iface->get_uri = gst_drm_src_uri_get_uri;
+  iface->set_uri = gst_drm_src_uri_set_uri;
 }
 /**
  * This function does the following:
@@ -608,7 +991,7 @@ static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
  */
 static gboolean plugin_init(GstPlugin* i_pPlugin)
 {
-       return gst_element_register(i_pPlugin, "drmsrc", GST_RANK_NONE, GST_TYPE_DRM_SRC);;
+  return gst_element_register(i_pPlugin, "drmsrc", GST_RANK_NONE, GST_TYPE_DRM_SRC);
 }
 /**
  * This function does the following:
@@ -616,12 +999,12 @@ static gboolean plugin_init(GstPlugin* i_pPlugin)
  *
  */
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-                                                GST_VERSION_MINOR,
-                                                "drmsrc",
-                                                "Plugin to read data from standad/DRM File",
-                                                plugin_init,
-                                                VERSION,
-                                                "LGPL",
-                                                "Samsung Electronics Co",
-                                                "http://www.samsung.com/")
+  GST_VERSION_MINOR,
+  "drmsrc",
+  "Plugin to read data from standad/DRM File",
+  plugin_init,
+  VERSION,
+  "LGPL",
+  "Samsung Electronics Co",
+  "http://www.samsung.com/")
 
index e47802e..3390b5c 100755 (executable)
@@ -28,6 +28,7 @@
 #include <sys/types.h>
 #include <gst/gst.h>
 #include <gst/base/gstbasesrc.h>
+#include <drm_trusted_client_types.h>
 #include <stdio.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #define O_BINARY (0)
 #endif
 
-#define ENABLE_PROFILING_INFO
-#ifdef ENABLE_PROFILING_INFO
-#define   PROFILE_FUNC_BEGIN\
-       char *newname; \
-       newname=__FUNCTION__; \ 
-       gst_ta_accum_item_begin(newname,FALSE,__FILE__,__LINE__);       
-       
-#define PROFILE_FUNC_END  \    
-       gst_ta_accum_item_end(newname,FALSE,__FILE__,__LINE__);
-
-#define PROFILE_BLOCK_BEGIN(name)              gst_ta_accum_item_begin(name,FALSE,__FILE__,__LINE__);
-#define PROFILE_BLOCK_END(name)                gst_ta_accum_item_end(name,FALSE,__FILE__,__LINE__);
-#define PROFILE_INIT                                           gst_ta_init();
-#define PROFILE_SHOW_RESULT                    gst_ta_accum_show_result(0);//MMTA_SHOW_FILE);  
-#define PROFILE_CLEAR_DATA                             gst_ta_release();
-#else
-#define PROFILE_FUNC_BEGIN
-#define PROFILE_FUNC_END
-#define PROFILE_BLOCK_BEGIN(name)
-#define PROFILE_BLOCK_END(name)
-#define PROFILE_INIT
-#define PROFILE_SHOW_RESULT
-#define PROFILE_CLEAR_DATA 
-#endif
 G_BEGIN_DECLS
 
 #define GST_TYPE_DRM_SRC (gst_drm_src_get_type())
@@ -90,8 +67,17 @@ struct _GstDrmSrc
        gchar *uri;                              
        gint fd;                                 
        guint64 read_position;  
-      gboolean seekable;      
+       gboolean seekable;
        gboolean is_regular;    
+       gboolean is_drm;          // flag indicating drm file
+       DRM_DECRYPT_HANDLE hfile;
+       gboolean is_playready;
+       gboolean is_oma;
+       gboolean event_posted;
+       gboolean isopen;
+#ifdef CONTROL_PAGECACHE
+       guint64 accum;
+#endif
 };
 
 struct _GstDrmSrcClass 
old mode 100644 (file)
new mode 100755 (executable)
index 9539702..3113f09
 {\
 g_object_set(G_OBJECT(x_queue), \
                        "max-size-bytes", (guint)x_byte, \
-                       "max-size-buffers", (guint)x_buffer, \  
+                       "max-size-buffers", (guint)x_buffer, \
                        "max-size-time", (guint64)(x_time*GST_SECOND), \
                        NULL); \
                        GST_INFO("Set to [%s], max [%d] byte, max [%d] buffer, max [%d] time(sec) ", GST_OBJECT_NAME(x_queue), x_byte, x_buffer, x_time);\
 }
 #else
-#define ENCODER_QUEUE_SET(x_queue, x_byte, x_buffer, x_time) 
+#define ENCODER_QUEUE_SET(x_queue, x_byte, x_buffer, x_time)
 #endif
 
-#define _GST_PAD_LINK_UNREF( srcpad, sinkpad, if_fail_goto )\
+#define _GST_PAD_LINK_UNREF(srcpad, sinkpad, if_fail_goto)\
 {\
-      GstPadLinkReturn ret = _GST_PAD_LINK( srcpad, sinkpad );\
-      gst_object_unref( srcpad ); srcpad = NULL;\
-      gst_object_unref( sinkpad ); sinkpad = NULL;\
-      if( ret != GST_PAD_LINK_OK) goto if_fail_goto;\
+      GstPadLinkReturn ret = _GST_PAD_LINK(srcpad, sinkpad);\
+      if(ret != GST_PAD_LINK_OK) { \
+            GstObject *src_parent = gst_pad_get_parent(srcpad);\
+            GstObject *sink_parent = gst_pad_get_parent(sinkpad);\
+            char *src_name = NULL;\
+            char *sink_name = NULL;\
+            g_object_get((GObject *)src_parent, "name", &src_name, NULL);\
+            g_object_get((GObject *)sink_parent, "name", &sink_name, NULL);\
+            GST_ERROR("src[%s] - sink[%s] link failed", src_name, sink_name);\
+            gst_object_unref(src_parent); src_parent = NULL;\
+            gst_object_unref(sink_parent); sink_parent = NULL;\
+            if (src_name) {\
+                  free(src_name); src_name = NULL;\
+            }\
+            if (sink_name) {\
+                  free(sink_name); sink_name = NULL;\
+            }\
+            gst_object_unref(srcpad); srcpad = NULL;\
+            gst_object_unref(sinkpad); sinkpad = NULL;\
+            goto if_fail_goto;\
+      }\
+      gst_object_unref(srcpad); srcpad = NULL;\
+      gst_object_unref(sinkpad); sinkpad = NULL;\
 }
 
-#define _GST_PAD_UNLINK_UNREF( srcpad, sinkpad)\
+#define _GST_PAD_UNLINK_UNREF(srcpad, sinkpad)\
 {\
-      gst_pad_unlink( srcpad, sinkpad );\
-      gst_object_unref( srcpad ); srcpad = NULL;\
-      gst_object_unref( sinkpad ); sinkpad = NULL;\
+      gst_pad_unlink(srcpad, sinkpad);\
+      gst_object_unref(srcpad); srcpad = NULL;\
+      gst_object_unref(sinkpad); sinkpad = NULL;\
 }
 
-#define DEFAULT_PROP_PROFILE             0
-#define DEFAULT_PROP_HIGH_SPEED                0
-#define DEFAULT_PROP_VENC_NAME "ffenc_h263"
-#define DEFAULT_PROP_AENC_NAME "secenc_amr"
-#define DEFAULT_PROP_IENC_NAME "jpegenc"
-#define DEFAULT_PROP_MUX_NAME  "ffmux_3gp" 
+#define DEFAULT_PROP_PROFILE            0
+#define DEFAULT_PROP_HIGH_SPEED         0
+#define DEFAULT_PROP_VENC_NAME          "ffenc_h263"
+#define DEFAULT_PROP_AENC_NAME          "secenc_amr"
+#define DEFAULT_PROP_IENC_NAME          "jpegenc"
+#define DEFAULT_PROP_MUX_NAME           "ffmux_3gp"
+#define DEFAULT_PROP_VCONV_NAME         "ffmpegcolorspace"
 
 /* props */
 enum
@@ -96,8 +116,9 @@ enum
        //elements name
        PROP_VENC_NAME,
        PROP_AENC_NAME,
-       PROP_IENC_NAME, 
-       PROP_MUX_NAME, 
+       PROP_IENC_NAME,
+       PROP_MUX_NAME,
+       PROP_VCONV_NAME,
        //caps
        PROP_VCAPS,
        PROP_ACAPS,
@@ -108,13 +129,14 @@ enum
        PROP_AUTO_COLORSPACE,
        PROP_BLOCK,
        PROP_PAUSE,
-       PROP_VENC_QUEUE,        
+       PROP_VENC_QUEUE,
        PROP_AENC_QUEUE,
        //elements pointer
        PROP_VIDEO_ENC,
        PROP_AUDIO_ENC,
        PROP_IMAGE_ENC,
        PROP_MUX,
+       PROP_VIDEO_CONV,
        //options
        PROP_USE_VIDEO_TOGGLE,
 };
@@ -124,9 +146,9 @@ enum
 enum
 {
   SIGNAL_STREAM_BLOCK,
-  SIGNAL_STREAM_UNBLOCK,       
+  SIGNAL_STREAM_UNBLOCK,
   SIGNAL_STREAM_PAUSE,
-  SIGNAL_STREAM_RESUME,  
+  SIGNAL_STREAM_RESUME,
   LAST_SIGNAL
 };
 #endif
@@ -135,7 +157,8 @@ typedef enum {
        ENCODEBIN_ELEMENT_VENC,
        ENCODEBIN_ELEMENT_AENC,
        ENCODEBIN_ELEMENT_IENC,
-       ENCODEBIN_ELEMENT_MUX
+       ENCODEBIN_ELEMENT_MUX,
+       ENCODEBIN_ELEMENT_VIDEO_CONV
 }GstEncodeBinElement;
 
 typedef enum {
@@ -388,7 +411,7 @@ GST_STATIC_CAPS ( \
     "height = (int) [ 1, 2147483647 ]," \
     "framerate = (fraction) [ 0/1, 2147483647/1 ]," \
     "format = (fourcc) AYUV " \
-)      
+)
 
 
 static GstStaticPadTemplate encoder_bin_src_template =
@@ -533,16 +556,16 @@ queue_overun_cb (GstElement * queue, GstEncodeBin *encodebin)
 
        GstClockTime now = gst_util_get_timestamp ();
 
-       g_object_get(G_OBJECT(queue), "current-level-bytes", &queue_size, 
+       g_object_get(G_OBJECT(queue), "current-level-bytes", &queue_size,
                                                                "current-level-buffers", &queue_bufnum,
        //                                                      "current-level-time", &queue_time,
                                                                NULL);
        GST_ELEMENT_WARNING (encodebin, STREAM, TOO_LAZY,
-           ("[%" GST_TIME_FORMAT "][%s], [%u b], [%u]", 
-           GST_TIME_ARGS(now), GST_OBJECT_NAME(queue), queue_size, queue_bufnum), (NULL)); 
+           ("[%" GST_TIME_FORMAT "][%s], [%u b], [%u]",
+           GST_TIME_ARGS(now), GST_OBJECT_NAME(queue), queue_size, queue_bufnum), (NULL));
 #else
        GST_ELEMENT_WARNING (encodebin, STREAM, TOO_LAZY,
-           ("%s overrun", GST_OBJECT_NAME(queue)), (NULL)); 
+           ("%s overrun", GST_OBJECT_NAME(queue)), (NULL));
 #endif
 }
 
@@ -570,10 +593,13 @@ gst_encode_bin_get_property (GObject * object,
                        break;
                case PROP_IENC_NAME:
                        g_value_set_string (value, encodebin->ienc_name);
-                       break; 
+                       break;
                case PROP_MUX_NAME:
                        g_value_set_string (value, encodebin->mux_name);
-                       break; 
+                       break;
+               case PROP_VCONV_NAME:
+                       g_value_set_string (value, encodebin->vconv_name);
+                       break;
                //caps
                case PROP_VCAPS:
                        gst_value_set_caps (value, encodebin->vcaps);
@@ -604,25 +630,25 @@ gst_encode_bin_get_property (GObject * object,
 //                     g_value_set_boolean (value, encodebin->use_venc_queue);
                        if((encodebin->video_encode_queue == NULL) && (encodebin->profile == GST_ENCODE_BIN_PROFILE_AV)) {
                                encodebin->video_encode_queue = gst_element_factory_make ("queue", "video_encode_queue");
-                               if(encodebin->video_encode_queue != NULL) 
+                               if(encodebin->video_encode_queue != NULL)
                                        gst_bin_add(GST_BIN(encodebin), encodebin->video_encode_queue);
                        }
-                       g_value_set_object (value, encodebin->video_encode_queue);              
-                       break;          
+                       g_value_set_object (value, encodebin->video_encode_queue);
+                       break;
                case PROP_AENC_QUEUE:
 //                     g_value_set_boolean (value, encodebin->use_aenc_queue);
                        if((encodebin->audio_encode_queue == NULL) && (encodebin->profile <= GST_ENCODE_BIN_PROFILE_AUDIO)) {
                                encodebin->audio_encode_queue = gst_element_factory_make ("queue", "audio_encode_queue");
-                               if(encodebin->audio_encode_queue != NULL) 
+                               if(encodebin->audio_encode_queue != NULL)
                                        gst_bin_add(GST_BIN(encodebin), encodebin->audio_encode_queue);
                        }
-                       g_value_set_object (value, encodebin->audio_encode_queue);                                      
-                       break;                                          
+                       g_value_set_object (value, encodebin->audio_encode_queue);
+                       break;
                //elements pointer
                case PROP_VIDEO_ENC:
                        if((encodebin->video_encode == NULL) && (encodebin->profile == GST_ENCODE_BIN_PROFILE_AV)) {
-                               encodebin->video_encode = gst_element_factory_make (encodebin->venc_name, "video_encode");
-                               if(encodebin->video_encode != NULL) 
+                               encodebin->video_encode = gst_element_factory_make (encodebin->venc_name, NULL);
+                               if(encodebin->video_encode != NULL)
                                        gst_bin_add(GST_BIN(encodebin), encodebin->video_encode);
                        }
                        g_value_set_object (value, encodebin->video_encode);
@@ -630,7 +656,7 @@ gst_encode_bin_get_property (GObject * object,
                case PROP_AUDIO_ENC:
                        if(encodebin->audio_encode == NULL && (encodebin->profile <= GST_ENCODE_BIN_PROFILE_AUDIO)) {
                                encodebin->audio_encode = gst_element_factory_make (encodebin->aenc_name, "audio_encode");
-                               if(encodebin->audio_encode != NULL) 
+                               if(encodebin->audio_encode != NULL)
                                        gst_bin_add(GST_BIN(encodebin), encodebin->audio_encode);
                        }
                        g_value_set_object (value, encodebin->audio_encode);
@@ -638,19 +664,27 @@ gst_encode_bin_get_property (GObject * object,
                case PROP_IMAGE_ENC:
                        if(encodebin->image_encode == NULL && (encodebin->profile == GST_ENCODE_BIN_PROFILE_IMAGE)) {
                                encodebin->image_encode = gst_element_factory_make (encodebin->ienc_name, "image_encode");
-                               if(encodebin->image_encode != NULL) 
+                               if(encodebin->image_encode != NULL)
                                        gst_bin_add(GST_BIN(encodebin), encodebin->image_encode);
                        }
                        g_value_set_object (value, encodebin->image_encode);
-                       break;  
+                       break;
                case PROP_MUX:
                        if(encodebin->mux == NULL && (encodebin->profile <= GST_ENCODE_BIN_PROFILE_AUDIO)) {
                                encodebin->mux = gst_element_factory_make (encodebin->mux_name, "mux");
-                               if(encodebin->mux != NULL) 
+                               if(encodebin->mux != NULL)
                                        gst_bin_add(GST_BIN(encodebin), encodebin->mux);
                        }
                        g_value_set_object (value, encodebin->mux);
                        break;
+               case PROP_VIDEO_CONV:
+                       if(encodebin->color_space == NULL && (encodebin->profile != GST_ENCODE_BIN_PROFILE_AUDIO)) {
+                               encodebin->color_space = gst_element_factory_make (encodebin->vconv_name, "video_convert");
+                               if(encodebin->color_space != NULL)
+                                       gst_bin_add(GST_BIN(encodebin), encodebin->color_space);
+                       }
+                       g_value_set_object (value, encodebin->color_space);
+                       break;
                case PROP_USE_VIDEO_TOGGLE:
                        g_value_set_boolean( value, encodebin->use_video_toggle );
                        break;
@@ -676,7 +710,7 @@ gst_encode_bin_set_property (GObject * object,
                        if(encodebin->profile != newprofile) {
                          gst_encode_bin_change_profile(encodebin, newprofile);
                        encodebin->profile = newprofile;
-                               }      
+                               }
                        */
                        break;
                case PROP_HIGH_SPEED:
@@ -691,17 +725,17 @@ gst_encode_bin_set_property (GObject * object,
                        new_name = g_value_get_string (value);
 
                        if(encodebin->video_encode == NULL) {
-                               if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_VENC, new_name))             
+                               if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_VENC, new_name))
                                        encodebin->venc_name = g_strdup (new_name);
                        } else {
                                if(strcmp (encodebin->venc_name, new_name)) {
                                        gst_encode_bin_remove_element(encodebin, encodebin->video_encode);
-                                       if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_VENC, new_name))             
-                                       encodebin->venc_name = g_strdup (new_name);
+                                       if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_VENC, new_name))
+                                               encodebin->venc_name = g_strdup (new_name);
                                }
                        }
                        break;
-               }  
+               }
                case PROP_AENC_NAME: {
                        const gchar  *new_name;
                        if(encodebin->profile > GST_ENCODE_BIN_PROFILE_AUDIO) {
@@ -711,13 +745,13 @@ gst_encode_bin_set_property (GObject * object,
                        new_name = g_value_get_string (value);
 
                        if(encodebin->audio_encode == NULL) {
-                               if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_AENC, new_name))             
+                               if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_AENC, new_name))
                                        encodebin->aenc_name = g_strdup (new_name);
                        } else {
                                if(strcmp (encodebin->aenc_name, new_name)) {
                                        gst_encode_bin_remove_element(encodebin, encodebin->audio_encode);
-                                       if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_AENC, new_name))             
-                                       encodebin->aenc_name = g_strdup (new_name);
+                                       if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_AENC, new_name))
+                                               encodebin->aenc_name = g_strdup (new_name);
                                }
                        }
                        break;
@@ -731,16 +765,16 @@ gst_encode_bin_set_property (GObject * object,
                        new_name = g_value_get_string (value);
 
                        if(encodebin->image_encode == NULL) {
-                               if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_IENC, new_name))             
+                               if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_IENC, new_name))
                                        encodebin->ienc_name = g_strdup (new_name);
                        } else {
                                if(strcmp (encodebin->ienc_name, new_name)) {
                                        gst_encode_bin_remove_element(encodebin, encodebin->image_encode);
-                                       if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_IENC, new_name))             
-                                       encodebin->ienc_name = g_strdup (new_name);
+                                       if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_IENC, new_name))
+                                               encodebin->ienc_name = g_strdup (new_name);
                                }
                        }
-                       break; 
+                       break;
                }
                case PROP_MUX_NAME: {
                        const gchar  *new_name;
@@ -751,16 +785,36 @@ gst_encode_bin_set_property (GObject * object,
                        new_name = g_value_get_string (value);
 
                        if(encodebin->mux == NULL) {
-                               if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_MUX, new_name))              
+                               if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_MUX, new_name))
                                        encodebin->mux_name = g_strdup (new_name);
                        } else {
                                if(strcmp (encodebin->mux_name, new_name)) {
                                        gst_encode_bin_remove_element(encodebin, encodebin->mux);
-                                       if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_MUX, new_name))              
-                                       encodebin->mux_name = g_strdup (new_name);
+                                       if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_MUX, new_name))
+                                               encodebin->mux_name = g_strdup (new_name);
+                               }
+                       }
+                       break;
+               }
+               case PROP_VCONV_NAME: {
+                       const gchar  *new_name;
+                       if (encodebin->profile == GST_ENCODE_BIN_PROFILE_AUDIO) {
+                               GST_WARNING_OBJECT(encodebin, "Profile isn't match");
+                               break;
+                       }
+                       new_name = g_value_get_string(value);
+
+                       if (encodebin->color_space == NULL) {
+                               if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_VIDEO_CONV, new_name))
+                                       encodebin->vconv_name = g_strdup (new_name);
+                       } else {
+                               if(strcmp (encodebin->vconv_name, new_name)) {
+                                       gst_encode_bin_remove_element(encodebin, encodebin->color_space);
+                                       if(gst_encode_bin_add_element_by_name(encodebin, ENCODEBIN_ELEMENT_VIDEO_CONV, new_name))
+                                               encodebin->vconv_name = g_strdup (new_name);
                                }
                        }
-                       break; 
+                       break;
                }
                //caps
                case PROP_VCAPS: {
@@ -828,23 +882,23 @@ gst_encode_bin_set_property (GObject * object,
                        gboolean newval = g_value_get_boolean (value);
                        if(encodebin->block != newval) {
                                if(!gst_encode_bin_block(encodebin, newval)) {
-#ifdef GST_ENCODE_BIN_SIGNAL_ENABLE            
+#ifdef GST_ENCODE_BIN_SIGNAL_ENABLE
                                        if(newval) {
                                                g_signal_emit (G_OBJECT (encodebin), gst_encode_bin_signals[SIGNAL_STREAM_BLOCK], 0, FALSE);
                                        } else {
                                                g_signal_emit (G_OBJECT (encodebin), gst_encode_bin_signals[SIGNAL_STREAM_UNBLOCK], 0, FALSE);
                                        }
-#endif                                 
+#endif
                                        break;
-                               }                               
+                               }
                        }
-#ifdef GST_ENCODE_BIN_SIGNAL_ENABLE            
+#ifdef GST_ENCODE_BIN_SIGNAL_ENABLE
                        if(newval) {
                                g_signal_emit (G_OBJECT (encodebin), gst_encode_bin_signals[SIGNAL_STREAM_BLOCK], 0, TRUE);
                        } else {
                                g_signal_emit (G_OBJECT (encodebin), gst_encode_bin_signals[SIGNAL_STREAM_UNBLOCK], 0, TRUE);
                        }
-#endif                 
+#endif
                        break;
                }
                case PROP_PAUSE: {
@@ -853,13 +907,13 @@ gst_encode_bin_set_property (GObject * object,
                                if(!gst_encode_bin_pause(encodebin, newval))
                                        break;
                        }
-#ifdef GST_ENCODE_BIN_SIGNAL_ENABLE            
+#ifdef GST_ENCODE_BIN_SIGNAL_ENABLE
                        if(newval) {
                                g_signal_emit (G_OBJECT (encodebin), gst_encode_bin_signals[SIGNAL_STREAM_PAUSE], 0, TRUE);
                        } else {
                                g_signal_emit (G_OBJECT (encodebin), gst_encode_bin_signals[SIGNAL_STREAM_RESUME], 0, TRUE);
                        }
-#endif                 
+#endif
                        break;
                }
                case PROP_VENC_QUEUE:
@@ -879,7 +933,7 @@ gst_encode_bin_set_property (GObject * object,
                        }
                        break;
                }
-                 break;                
+                 break;
                case PROP_AENC_QUEUE:
 //               encodebin->use_aenc_queue = g_value_get_boolean (value);
                {
@@ -897,8 +951,8 @@ gst_encode_bin_set_property (GObject * object,
                        }
                        break;
                }
-                 break;                  
-               case PROP_VIDEO_ENC: 
+                 break;
+               case PROP_VIDEO_ENC:
                {
                        GstElement *newelement = g_value_get_object (value);
                        if(encodebin->profile > GST_ENCODE_BIN_PROFILE_AV) {
@@ -914,7 +968,7 @@ gst_encode_bin_set_property (GObject * object,
                        }
                        break;
                }
-               case PROP_AUDIO_ENC: 
+               case PROP_AUDIO_ENC:
                {
                        GstElement *newelement = g_value_get_object (value);
                        if(encodebin->profile > GST_ENCODE_BIN_PROFILE_AUDIO) {
@@ -960,6 +1014,21 @@ gst_encode_bin_set_property (GObject * object,
                        }
                        break;
                }
+               case PROP_VIDEO_CONV: {
+                       GstElement *newelement = g_value_get_object (value);
+                       if(encodebin->profile == GST_ENCODE_BIN_PROFILE_AUDIO) {
+                               GST_WARNING_OBJECT(encodebin, "Profile isn't match, change profile first!");
+                               break;
+                       }
+                       if(newelement != NULL) {
+                               gst_encode_bin_remove_element(encodebin, encodebin->color_space);
+                               encodebin->color_space = newelement;
+                               gst_object_ref (encodebin->color_space);
+                               gst_object_sink (GST_OBJECT_CAST (encodebin->color_space));
+                               gst_bin_add(GST_BIN(encodebin), encodebin->color_space);
+                       }
+                       break;
+               }
                case PROP_USE_VIDEO_TOGGLE:
                        encodebin->use_video_toggle = g_value_get_boolean( value );
                        break;
@@ -987,12 +1056,12 @@ gst_encode_bin_request_new_pad (GstElement * element,
        g_return_val_if_fail (GST_IS_ENCODE_BIN (element), NULL);
 
        encodebin = GST_ENCODE_BIN (element);
-  
+
  /* FIXME */
        if (templ == gst_element_class_get_pad_template (klass, "audio")) {
                if (encodebin->profile <= GST_ENCODE_BIN_PROFILE_AUDIO) {
                        gst_encode_bin_init_audio_elements(element, NULL); //??
-                       
+
                        if(encodebin->audio_sinkpad == NULL)
                        {
                                pad = gst_element_get_static_pad (encodebin->audio_queue, "sink");
@@ -1002,10 +1071,10 @@ gst_encode_bin_request_new_pad (GstElement * element,
                        }
                        else
                        {
-                               GST_WARNING_OBJECT (GST_IS_ENCODE_BIN (element), "encodebin: audio pad is aleady existed, return existing audio pad\n");                        
+                               GST_WARNING_OBJECT (GST_IS_ENCODE_BIN (element), "encodebin: audio pad is aleady existed, return existing audio pad\n");
                                return encodebin->audio_sinkpad;
                        }
-                       
+
                        gst_element_add_pad (element, encodebin->audio_sinkpad);
                        gst_pad_set_setcaps_function (encodebin->audio_sinkpad,
                                GST_DEBUG_FUNCPTR (gst_encode_bin_audsink_set_caps));
@@ -1019,16 +1088,16 @@ gst_encode_bin_request_new_pad (GstElement * element,
                        if(encodebin->video_sinkpad == NULL)
                        {
                                pad = gst_element_get_static_pad (encodebin->video_queue, "sink");
-                               encodebin->video_sinkpad = gst_ghost_pad_new ("video", pad);        
+                               encodebin->video_sinkpad = gst_ghost_pad_new ("video", pad);
                                gst_object_unref(pad);
                                pad = NULL;
                        }
                        else
                        {
-                               GST_WARNING_OBJECT (GST_IS_ENCODE_BIN (element), "encodebin: video pad is aleady existed, return existing video pad\n");                                                
+                               GST_WARNING_OBJECT (GST_IS_ENCODE_BIN (element), "encodebin: video pad is aleady existed, return existing video pad\n");
                                return encodebin->video_sinkpad;
                        }
-                       
+
                        gst_element_add_pad (element, encodebin->video_sinkpad);
                        gst_pad_set_setcaps_function (encodebin->video_sinkpad,
                        GST_DEBUG_FUNCPTR (gst_encode_bin_vidsink_set_caps));
@@ -1041,14 +1110,14 @@ gst_encode_bin_request_new_pad (GstElement * element,
                                pad = gst_element_get_static_pad (encodebin->image_queue, "sink");
                                encodebin->image_sinkpad = gst_ghost_pad_new ("image", pad);
                                gst_object_unref(pad);
-                               pad = NULL;                             
+                               pad = NULL;
                        }
                        else
                        {
-                               GST_WARNING_OBJECT (GST_IS_ENCODE_BIN (element), "encodebin: image pad is aleady existed, return existing image pad\n");                        
+                               GST_WARNING_OBJECT (GST_IS_ENCODE_BIN (element), "encodebin: image pad is aleady existed, return existing image pad\n");
                                return encodebin->image_sinkpad;
                        }
-                       
+
                        gst_element_add_pad (element, encodebin->image_sinkpad);
                        gst_pad_set_setcaps_function (encodebin->image_sinkpad,
                        GST_DEBUG_FUNCPTR (gst_encode_bin_imgsink_set_caps));
@@ -1058,33 +1127,32 @@ gst_encode_bin_request_new_pad (GstElement * element,
        } else {
                if (encodebin->profile == GST_ENCODE_BIN_PROFILE_IMAGE) {
                        gst_encode_bin_init_image_elements(element, NULL); //??
-                       
+
                        if(encodebin->image_sinkpad == NULL)
                        {
                                pad = gst_element_get_static_pad (encodebin->image_queue, "sink");
                                encodebin->image_sinkpad = gst_ghost_pad_new ("image", pad);
                                gst_object_unref(pad);
-                               pad = NULL;                             
+                               pad = NULL;
                        }
                        else
                        {
-                               GST_WARNING_OBJECT (GST_IS_ENCODE_BIN (element), "encodebin: image pad is aleady existed, return existing image pad\n");                        
+                               GST_WARNING_OBJECT (GST_IS_ENCODE_BIN (element), "encodebin: image pad is aleady existed, return existing image pad\n");
                                return encodebin->image_sinkpad;
                        }
-                       
+
                        gst_element_add_pad (element, encodebin->image_sinkpad);
                        gst_pad_set_setcaps_function (encodebin->image_sinkpad,
                        GST_DEBUG_FUNCPTR (gst_encode_bin_imgsink_set_caps));
                        return encodebin->image_sinkpad;
                } else
-                       return NULL;        
-       }  
+                       return NULL;
+       }
 }
 
 static void
 gst_encode_bin_class_init (GstEncodeBinClass *klass)
 {
-
        GObjectClass *gobject_klass;
        GstElementClass *gstelement_klass;
        GstBinClass *gstbin_klass;
@@ -1092,12 +1160,12 @@ gst_encode_bin_class_init (GstEncodeBinClass *klass)
        gobject_klass = (GObjectClass *) klass;
        gstelement_klass = (GstElementClass *) klass;
        gstbin_klass = (GstBinClass *) klass;
-       
+
        parent_class = g_type_class_peek_parent (klass);
 
        gobject_klass->get_property = gst_encode_bin_get_property;
        gobject_klass->set_property = gst_encode_bin_set_property;
-       gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_encode_bin_dispose);    
+       gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_encode_bin_dispose);
        gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_encode_bin_finalize);
 
 
@@ -1107,7 +1175,7 @@ gst_encode_bin_class_init (GstEncodeBinClass *klass)
              G_PARAM_READWRITE));
 
        g_object_class_install_property (gobject_klass, PROP_HIGH_SPEED,
-         g_param_spec_int ("high-speed-fps", "high speed rec. fps", "framerate for high speed recording", 0, G_MAXINT, 
+         g_param_spec_int ("high-speed-fps", "high speed rec. fps", "framerate for high speed recording", 0, G_MAXINT,
                DEFAULT_PROP_HIGH_SPEED, G_PARAM_READWRITE));
 
        g_object_class_install_property (gobject_klass, PROP_VENC_NAME,
@@ -1126,6 +1194,10 @@ gst_encode_bin_class_init (GstEncodeBinClass *klass)
          g_param_spec_string ("mux-name", "muxer name", "the name of muxer to use",
              DEFAULT_PROP_MUX_NAME, G_PARAM_READWRITE));
 
+       g_object_class_install_property (gobject_klass, PROP_VCONV_NAME,
+         g_param_spec_string ("vconv-name", "Video converter name", "the name of video color converter to use",
+             DEFAULT_PROP_VCONV_NAME, G_PARAM_READWRITE));
+
        g_object_class_install_property (gobject_klass, PROP_VCAPS,
          g_param_spec_boxed ("vcaps", "caps for video","caps for video recording",
              GST_TYPE_CAPS, G_PARAM_READWRITE));
@@ -1161,11 +1233,11 @@ gst_encode_bin_class_init (GstEncodeBinClass *klass)
 #if 0
        g_object_class_install_property (gobject_klass, PROP_VENC_QUEUE,
          g_param_spec_boolean ("use-venc-queue", "use queue between venc and mux",
-             "add queue between venc and mux(only for custom optimization)", FALSE, G_PARAM_READWRITE));       
+             "add queue between venc and mux(only for custom optimization)", FALSE, G_PARAM_READWRITE));
 
        g_object_class_install_property (gobject_klass, PROP_AENC_QUEUE,
          g_param_spec_boolean ("use-aenc-queue", "use queue between aenc and mux",
-             "add queue between aenc and mux(only for custom optimization)", FALSE, G_PARAM_READWRITE));               
+             "add queue between aenc and mux(only for custom optimization)", FALSE, G_PARAM_READWRITE));
 #else
        g_object_class_install_property (gobject_klass, PROP_VENC_QUEUE,
          g_param_spec_object ("use-venc-queue", "Video Encoder queue",
@@ -1198,6 +1270,11 @@ gst_encode_bin_class_init (GstEncodeBinClass *klass)
              "the muxer element to use",
              GST_TYPE_ELEMENT, G_PARAM_READWRITE));
 
+       g_object_class_install_property (gobject_klass, PROP_VIDEO_CONV,
+         g_param_spec_object ("video-convert", "Video converter",
+             "the video converter element to use",
+             GST_TYPE_ELEMENT, G_PARAM_READWRITE));
+
        g_object_class_install_property (gobject_klass, PROP_USE_VIDEO_TOGGLE,
                g_param_spec_boolean ("use-video-toggle", "Use video toggle",
                "Use video toggle while AV recording", TRUE, G_PARAM_READWRITE));
@@ -1205,23 +1282,23 @@ gst_encode_bin_class_init (GstEncodeBinClass *klass)
 #ifdef GST_ENCODE_BIN_SIGNAL_ENABLE
        gst_encode_bin_signals[SIGNAL_STREAM_BLOCK] =
                g_signal_new ("stream-block", G_TYPE_FROM_CLASS (klass),
-               G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstEncodeBinClass, stream_block), 
+               G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstEncodeBinClass, stream_block),
                NULL, NULL, gst_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 
        gst_encode_bin_signals[SIGNAL_STREAM_UNBLOCK] =
                g_signal_new ("stream-unblock", G_TYPE_FROM_CLASS (klass),
-               G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstEncodeBinClass, stream_unblock), 
+               G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstEncodeBinClass, stream_unblock),
                NULL, NULL, gst_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 
        gst_encode_bin_signals[SIGNAL_STREAM_PAUSE] =
                g_signal_new ("stream-pause", G_TYPE_FROM_CLASS (klass),
-               G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstEncodeBinClass, stream_pause), 
+               G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstEncodeBinClass, stream_pause),
                NULL, NULL, gst_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 
        gst_encode_bin_signals[SIGNAL_STREAM_RESUME] =
                g_signal_new ("stream-resume", G_TYPE_FROM_CLASS (klass),
-               G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstEncodeBinClass, stream_resume), 
-               NULL, NULL, gst_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); 
+               G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstEncodeBinClass, stream_resume),
+               NULL, NULL, gst_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 #endif
 
        gst_element_class_add_pad_template (gstelement_klass,
@@ -1237,7 +1314,7 @@ gst_encode_bin_class_init (GstEncodeBinClass *klass)
 
        gstelement_klass->request_new_pad =
          GST_DEBUG_FUNCPTR (gst_encode_bin_request_new_pad);
-       gstelement_klass->release_pad = 
+       gstelement_klass->release_pad =
          GST_DEBUG_FUNCPTR (gst_encode_bin_release_pad);
        gstelement_klass->change_state =
          GST_DEBUG_FUNCPTR (gst_encode_bin_change_state);
@@ -1248,17 +1325,17 @@ gst_encode_bin_init (GstEncodeBin *encodebin)
 {
        encodebin->mutex = g_mutex_new();
 
-       if(encodebin->srcpad == NULL) {
+       if (encodebin->srcpad == NULL) {
                encodebin->srcpad = gst_ghost_pad_new_no_target ("src", GST_PAD_SRC);
                gst_element_add_pad (GST_ELEMENT(encodebin), encodebin->srcpad);
-       }  
+       }
 
        encodebin->video_sinkpad = NULL;
        encodebin->audio_sinkpad = NULL;
        encodebin->image_sinkpad = NULL;
        encodebin->mux_audio_sinkpad = NULL;
        encodebin->mux_video_sinkpad = NULL;
-       
+
        encodebin->profile = DEFAULT_PROP_PROFILE;
        encodebin->fps = 0;
        encodebin->high_speed_fps = DEFAULT_PROP_HIGH_SPEED;
@@ -1268,37 +1345,38 @@ gst_encode_bin_init (GstEncodeBin *encodebin)
        encodebin->auto_audio_resample = TRUE;
        encodebin->auto_color_space = TRUE;
        encodebin->block = FALSE;
-       encodebin->pause= FALSE; 
+       encodebin->pause= FALSE;
        encodebin->use_video_toggle = TRUE;
-       encodebin->use_venc_queue= FALSE;       
-       encodebin->use_aenc_queue= FALSE;               
+       encodebin->use_venc_queue= FALSE;
+       encodebin->use_aenc_queue= FALSE;
 
        encodebin->venc_name = g_strdup(DEFAULT_PROP_VENC_NAME);
        encodebin->aenc_name = g_strdup(DEFAULT_PROP_AENC_NAME);
-       encodebin->ienc_name = g_strdup(DEFAULT_PROP_IENC_NAME);  
-       encodebin->mux_name = g_strdup(DEFAULT_PROP_MUX_NAME);  
+       encodebin->ienc_name = g_strdup(DEFAULT_PROP_IENC_NAME);
+       encodebin->mux_name = g_strdup(DEFAULT_PROP_MUX_NAME);
+       encodebin->vconv_name = g_strdup(DEFAULT_PROP_VCONV_NAME);
 
        encodebin->vcaps = gst_caps_new_any ();
        encodebin->acaps = gst_caps_new_any ();
        encodebin->icaps = gst_caps_new_any ();
 
        encodebin->audio_queue = NULL;
-       encodebin->video_queue = NULL;  
-       encodebin->video_encode_queue = NULL;   
-       encodebin->image_queue = NULL;    
+       encodebin->video_queue = NULL;
+       encodebin->video_encode_queue = NULL;
+       encodebin->image_queue = NULL;
 
        encodebin->audio_encode = NULL;
        encodebin->video_encode = NULL;
-       encodebin->image_encode = NULL;  
+       encodebin->image_encode = NULL;
 
-       encodebin->vcapsfilter = NULL;  
-       encodebin->acapsfilter = NULL;    
-       encodebin->icapsfilter = NULL;      
+       encodebin->vcapsfilter = NULL;
+       encodebin->acapsfilter = NULL;
+       encodebin->icapsfilter = NULL;
 
-       encodebin->video_toggle = NULL;  
+       encodebin->video_toggle = NULL;
        encodebin->image_toggle = NULL;
-       encodebin->color_space = NULL;  
-       encodebin->audio_conv = NULL;  
+       encodebin->color_space = NULL;
+       encodebin->audio_conv = NULL;
        encodebin->audio_sample = NULL;
 
        encodebin->mux = NULL;
@@ -1310,11 +1388,11 @@ gst_encode_bin_init (GstEncodeBin *encodebin)
        encodebin->vsink_hs_probeid = 0;
        encodebin->asink_probeid = 0;
        encodebin->veque_sig_id = 0;
-       encodebin->aeque_sig_id = 0;    
+       encodebin->aeque_sig_id = 0;
 }
 
-static void 
-gst_encode_bin_dispose (GObject * object) 
+static void
+gst_encode_bin_dispose (GObject * object)
 {
        GstEncodeBin *encodebin = GST_ENCODE_BIN (object);
 
@@ -1322,7 +1400,7 @@ gst_encode_bin_dispose (GObject * object)
        encodebin->venc_name = NULL;
 
        g_free(encodebin->aenc_name);
-       encodebin->aenc_name = NULL;    
+       encodebin->aenc_name = NULL;
 
        g_free(encodebin->ienc_name);
        encodebin->ienc_name = NULL;
@@ -1330,22 +1408,20 @@ gst_encode_bin_dispose (GObject * object)
        g_free(encodebin->mux_name);
        encodebin->mux_name = NULL;
 
+       g_free(encodebin->vconv_name);
+       encodebin->vconv_name = NULL;
 
        gst_caps_replace (&encodebin->vcaps, NULL);
        gst_caps_replace (&encodebin->acaps, NULL);
        gst_caps_replace (&encodebin->icaps, NULL);
 
-       if(encodebin->srcpad != NULL)
-       {
-               gst_element_remove_pad (GST_ELEMENT(encodebin), encodebin->srcpad);
+       if (encodebin->srcpad != NULL) {
+               gst_element_remove_pad(GST_ELEMENT(encodebin), encodebin->srcpad);
                encodebin->srcpad = NULL;
        }
-               
 
        G_OBJECT_CLASS (parent_class)->dispose (object);
 
-
-
        encodebin->video_sinkpad = NULL;
        encodebin->audio_sinkpad = NULL;
        encodebin->image_sinkpad = NULL;
@@ -1353,34 +1429,33 @@ gst_encode_bin_dispose (GObject * object)
        encodebin->mux_video_sinkpad = NULL;
 
        encodebin->audio_queue = NULL;
-       encodebin->video_queue = NULL;  
-       encodebin->image_queue = NULL;    
+       encodebin->video_queue = NULL;
+       encodebin->image_queue = NULL;
 
        encodebin->audio_encode = NULL;
        encodebin->video_encode = NULL;
-       encodebin->video_encode_queue = NULL;   
-       encodebin->image_encode = NULL;  
+       encodebin->video_encode_queue = NULL;
+       encodebin->image_encode = NULL;
 
-       encodebin->vcapsfilter = NULL;  
-       encodebin->acapsfilter = NULL;    
-       encodebin->icapsfilter = NULL;      
+       encodebin->vcapsfilter = NULL;
+       encodebin->acapsfilter = NULL;
+       encodebin->icapsfilter = NULL;
 
-       encodebin->video_toggle = NULL;  
+       encodebin->video_toggle = NULL;
        encodebin->image_toggle = NULL;
-       encodebin->color_space = NULL;  
-       encodebin->audio_conv = NULL;  
+       encodebin->color_space = NULL;
+       encodebin->audio_conv = NULL;
        encodebin->audio_sample = NULL;
-       
-       if(encodebin->mux && GST_IS_ELEMENT(encodebin->mux))
-       {
-               int remain_count= 0 ;
+
+       if (encodebin->mux && GST_IS_ELEMENT(encodebin->mux)) {
+               int remain_count= 0;
                remain_count = GST_OBJECT_REFCOUNT_VALUE(encodebin->mux);
-               while(remain_count)
-               {
+               while (remain_count) {
                        gst_object_unref(encodebin->mux);
                        remain_count--;
-               }               
+               }
        }
+
        encodebin->mux = NULL;
 }
 
@@ -1427,8 +1502,8 @@ gst_encode_bin_change_state (GstElement * element, GstStateChange transition)
        case GST_STATE_CHANGE_PAUSED_TO_READY:
                break;
        case GST_STATE_CHANGE_READY_TO_NULL:
-               gst_encode_bin_unlink_elements(encode_bin);     
-               break;          
+               gst_encode_bin_unlink_elements(encode_bin);
+               break;
        default:
                break;
        }
@@ -1452,9 +1527,9 @@ gst_encode_bin_release_pad (GstElement * element, GstPad * pad)
 {
        GstEncodeBin *encodebin = GST_ENCODE_BIN (element);
        GstPad *muxpad = NULL;
-       
+
        if(!pad_compare_name(pad, "video")) {
-#if 0          
+#if 0
                gst_encode_bin_remove_element(encodebin, encodebin->video_queue);
                encodebin->video_queue = NULL;
                gst_encode_bin_remove_element(encodebin, encodebin->video_toggle);
@@ -1464,29 +1539,29 @@ gst_encode_bin_release_pad (GstElement * element, GstPad * pad)
                gst_encode_bin_remove_element(encodebin, encodebin->vcapsfilter);
                encodebin->vcapsfilter = NULL;
                gst_encode_bin_remove_element(encodebin, encodebin->video_encode_queue);
-               encodebin->video_encode_queue =  NULL;          
+               encodebin->video_encode_queue =  NULL;
                gst_encode_bin_remove_element(encodebin, encodebin->video_encode);
                encodebin->video_encode =  NULL;
 
-               gst_element_release_request_pad(encodebin->mux, encodebin->mux_video_sinkpad);  
+               gst_element_release_request_pad(encodebin->mux, encodebin->mux_video_sinkpad);
                encodebin->mux_video_sinkpad = NULL;
 
                if(encodebin->mux_audio_sinkpad == NULL) {
                        gst_encode_bin_remove_element(encodebin, encodebin->mux);
                        encodebin->mux = NULL;
                }
-               else 
+               else
                {
                        encodebin->mux_audio_sinkpad = NULL;
                }
-#endif 
+#endif
 
                if(encodebin->mux_video_sinkpad != NULL)
-               {       
+               {
                        gst_element_release_request_pad(encodebin->mux, encodebin->mux_video_sinkpad);
                        encodebin->mux_video_sinkpad = NULL;
                }
-               
+
                gst_pad_set_active (pad, FALSE); //??
                gst_element_remove_pad(element, pad);
                encodebin->video_sinkpad = NULL;
@@ -1501,7 +1576,7 @@ gst_encode_bin_release_pad (GstElement * element, GstPad * pad)
                gst_encode_bin_remove_element(encodebin, encodebin->acapsfilter);
                encodebin->acapsfilter = NULL;
                gst_encode_bin_remove_element(encodebin, encodebin->audio_encode_queue);
-               encodebin->audio_encode_queue =  NULL;                  
+               encodebin->audio_encode_queue =  NULL;
                gst_encode_bin_remove_element(encodebin, encodebin->audio_encode);
                encodebin->audio_encode = NULL;
 
@@ -1513,11 +1588,11 @@ gst_encode_bin_release_pad (GstElement * element, GstPad * pad)
                        gst_encode_bin_remove_element(encodebin, encodebin->mux);
                        encodebin->mux = NULL;
                }
-               else 
+               else
                {
                        encodebin->mux_video_sinkpad = NULL;
                }
-#endif         
+#endif
                if(encodebin->mux_audio_sinkpad != NULL)
                {
                        gst_element_release_request_pad(encodebin->mux, encodebin->mux_audio_sinkpad);
@@ -1525,7 +1600,7 @@ gst_encode_bin_release_pad (GstElement * element, GstPad * pad)
                        encodebin->mux_audio_sinkpad = NULL;
                }
 
-               gst_pad_set_active (pad, FALSE); //??           
+               gst_pad_set_active (pad, FALSE); //??
                gst_element_remove_pad(element, pad);
                encodebin->audio_sinkpad = NULL;
        } else {
@@ -1540,8 +1615,8 @@ gst_encode_bin_release_pad (GstElement * element, GstPad * pad)
                encodebin->icapsfilter = NULL;
                gst_encode_bin_remove_element(encodebin, encodebin->image_encode);
                encodebin->image_encode = NULL;
-#endif         
-               gst_pad_set_active (pad, FALSE); //??           
+#endif
+               gst_pad_set_active (pad, FALSE); //??
                gst_element_remove_pad(element, pad);
                encodebin->image_sinkpad = NULL;
        }
@@ -1559,60 +1634,74 @@ pad_compare_name (GstPad * pad1, const gchar * name)
        return result;
 }
 
-static gboolean 
+static gboolean
 gst_encode_bin_add_element_by_name (GstEncodeBin *encodebin, GstEncodeBinElement type, const gchar *name)
 {
        switch(type) {
-               case ENCODEBIN_ELEMENT_VENC :
-                       encodebin->video_encode = gst_element_factory_make (name, "video_encode");      
+               case ENCODEBIN_ELEMENT_VENC:
+                       encodebin->video_encode = gst_element_factory_make (name, NULL);
                        if(encodebin->video_encode != NULL) {
                                gst_bin_add(GST_BIN(encodebin), encodebin->video_encode);
                                g_free(encodebin->venc_name);
+                               encodebin->venc_name = NULL;
                        } else {
                                goto element_make_fail;
                        }
                        break;
-               case ENCODEBIN_ELEMENT_AENC :
-                       encodebin->audio_encode = gst_element_factory_make (name, "audio_encode");      
+               case ENCODEBIN_ELEMENT_AENC:
+                       encodebin->audio_encode = gst_element_factory_make (name, "audio_encode");
                        if(encodebin->audio_encode != NULL) {
                                gst_bin_add(GST_BIN(encodebin), encodebin->audio_encode);
                                g_free(encodebin->aenc_name);
+                               encodebin->aenc_name = NULL;
                        } else {
                                goto element_make_fail;
-                       }                       
+                       }
                        break;
-               case ENCODEBIN_ELEMENT_IENC :
-                       encodebin->image_encode = gst_element_factory_make (name, "image_encode");      
+               case ENCODEBIN_ELEMENT_IENC:
+                       encodebin->image_encode = gst_element_factory_make (name, "image_encode");
                        if(encodebin->image_encode != NULL) {
                                gst_bin_add(GST_BIN(encodebin), encodebin->image_encode);
                                g_free(encodebin->ienc_name);
+                               encodebin->ienc_name = NULL;
                        } else {
                                goto element_make_fail;
-                       }               
+                       }
                        break;
-               case ENCODEBIN_ELEMENT_MUX :
-                       encodebin->mux = gst_element_factory_make (name, "mux");        
+               case ENCODEBIN_ELEMENT_MUX:
+                       encodebin->mux = gst_element_factory_make (name, "mux");
                        if(encodebin->mux != NULL) {
                                gst_bin_add(GST_BIN(encodebin), encodebin->mux);
                                g_free(encodebin->mux_name);
+                               encodebin->mux_name = NULL;
                        } else {
                                goto element_make_fail;
-                       }               
+                       }
                        break;
-               default :       
+               case ENCODEBIN_ELEMENT_VIDEO_CONV:
+                       encodebin->color_space = gst_element_factory_make(name, "video_convert");
+                       if (encodebin->color_space != NULL) {
+                               gst_bin_add(GST_BIN(encodebin), encodebin->color_space);
+                               g_free(encodebin->vconv_name);
+                               encodebin->vconv_name = NULL;
+                       } else {
+                               goto element_make_fail;
+                       }
+                       break;
+               default:
                        GST_WARNING_OBJECT(encodebin, "Invalid element type = %d", type);
-                       break;  
+                       break;
        }
 
        return TRUE;
-       
+
 element_make_fail:
        GST_WARNING_OBJECT(encodebin, "no such element factory \"%s\"!", name);
        return FALSE;
 }
 
 #if 0 //disable unused function
-static gboolean 
+static gboolean
 gst_encode_bin_change_profile(GstEncodeBin *encodebin, gboolean newprofile)
 {
 
@@ -1658,7 +1747,7 @@ gst_encode_bin_change_profile(GstEncodeBin *encodebin, gboolean newprofile)
 
 }
 
-static void 
+static void
 gst_encode_bin_replace_element (GstEncodeBin *encodebin, gint type, GstElement * newelement)
 {
   if(newelement == NULL) {
@@ -1679,7 +1768,7 @@ gst_encode_bin_replace_element (GstEncodeBin *encodebin, gint type, GstElement *
        gst_object_ref (encodebin->audio_encode);
        gst_object_sink (GST_OBJECT_CAST (encodebin->audio_encode));
        gst_bin_add(GST_BIN(encodebin),  encodebin->audio_encode);
-       break;  
+       break;
     case PROP_IMAGE_ENC:
        gst_encode_bin_remove_element(encodebin, encodebin->image_encode);
        encodebin->image_encode = newelement;
@@ -1701,11 +1790,11 @@ gst_encode_bin_replace_element (GstEncodeBin *encodebin, gint type, GstElement *
   }
 }
 
-static gboolean 
+static gboolean
 gst_encode_bin_replace_element_by_name(GstEncodeBin *encodebin, GstEncodeBinElement type, const gchar *name)
 {
        GstPad *sink1, *sink2, *src, *peersink1, *peersink2, *peersrc;
-       
+
        switch(type) {
                case ENCODEBIN_ELEMENT_VENC:
                        if(encodebin->video_encode == NULL) {
@@ -1731,7 +1820,7 @@ gst_encode_bin_replace_element_by_name(GstEncodeBin *encodebin, GstEncodeBinElem
                                                }
                                        }
                                }
-                               
+
                                if(gst_encode_bin_remove_element(encodebin, encodebin->video_encode)) {
                                        if(encodebin->video_encode = gst_element_factory_make (name, "video_encode") != NULL) {
                                                gst_bin_add(GST_BIN(encodebin), encodebin->video_encode);
@@ -1740,7 +1829,7 @@ gst_encode_bin_replace_element_by_name(GstEncodeBin *encodebin, GstEncodeBinElem
                                                                goto link_fail;
                                                        }
                                                }
-                                               
+
                                                if(peersrc != NULL) {
                                                        if(!gst_pad_link(gst_element_get_pad(encodebin->video_encode, "src"), peersrc)) {
                                                                goto link_fail;
@@ -1748,13 +1837,13 @@ gst_encode_bin_replace_element_by_name(GstEncodeBin *encodebin, GstEncodeBinElem
                                                }
                                        } else {
                                                GST_ERROR_OBJECT(encodebin, "gst_encode_bin_replace_element_by_name() new element[%d] make fail\n", type);
-                                               return FALSE;                                   
+                                               return FALSE;
                                        }
                                } else {
                                        GST_ERROR_OBJECT(encodebin, "gst_encode_bin_replace_element_by_name() old element[%d] remove fail\n", type);
                                        return FALSE;
-                               }                               
-                       }                       
+                               }
+                       }
                        break;
                case ENCODEBIN_ELEMENT_AENC:
                        break;
@@ -1769,38 +1858,38 @@ gst_encode_bin_replace_element_by_name(GstEncodeBin *encodebin, GstEncodeBinElem
        gst_object_unref(sink1);
        gst_object_unref(sink2);
        gst_object_unref(src);
-       gst_object_unref(peersink1);    
-       gst_object_unref(peersink2);    
-       gst_object_unref(peersrc);              
+       gst_object_unref(peersink1);
+       gst_object_unref(peersink2);
+       gst_object_unref(peersrc);
        return TRUE;
 
 unlink_fail:
        gst_object_unref(sink1);
        gst_object_unref(sink2);
        gst_object_unref(src);
-       gst_object_unref(peersink1);    
-       gst_object_unref(peersink2);    
-       gst_object_unref(peersrc);      
+       gst_object_unref(peersink1);
+       gst_object_unref(peersink2);
+       gst_object_unref(peersrc);
        GST_ERROR_OBJECT(encodebin, "gst_encode_bin_replace_element_by_name() old element[%d] unlink fail\n", type);
        return FALSE;
 
-       
+
 link_fail:
        gst_object_unref(sink1);
        gst_object_unref(sink2);
        gst_object_unref(src);
-       gst_object_unref(peersink1);    
-       gst_object_unref(peersink2);    
-       gst_object_unref(peersrc);      
+       gst_object_unref(peersink1);
+       gst_object_unref(peersink2);
+       gst_object_unref(peersrc);
        GST_ERROR_OBJECT(encodebin, "gst_encode_bin_replace_element_by_name() new element[%d] link fail\n", type);
-       return FALSE;                   
+       return FALSE;
 }
 
-static gboolean 
+static gboolean
 gst_encode_bin_replace_element_by_object(GstEncodeBin *encodebin, GstEncodeBinElement type, GstElement * element)
 {
        GstPad *sink1, *sink2, *src, *peersink1, *peersink2, *peersrc;
-       
+
        switch(type)
                case ENCODEBIN_ELEMENT_VENC:
                        if(encodebin->video_encode == NULL) {
@@ -1819,15 +1908,17 @@ gst_encode_bin_replace_element_by_object(GstEncodeBin *encodebin, GstEncodeBinEl
 }
 #endif //disable unused function
 
-static gboolean 
+static gboolean
 gst_encode_bin_remove_element (GstEncodeBin *encodebin, GstElement * element)
 {
        GstObject *parent;
        gchar *ename = NULL;
-       GST_DEBUG_OBJECT (encodebin, "gst_encode_bin_remove_element");
+       GST_INFO_OBJECT (encodebin, "gst_encode_bin_remove_element");
 
-       if(element == NULL)
+       if (element == NULL) {
+               GST_INFO_OBJECT (encodebin, "element is already NULL");
                return TRUE;
+       }
 
        gst_element_set_state (element, GST_STATE_NULL);
        parent = gst_element_get_parent (element);
@@ -1839,37 +1930,46 @@ gst_encode_bin_remove_element (GstEncodeBin *encodebin, GstElement * element)
                        GST_ERROR_OBJECT (encodebin, "gst_encode_bin_remove_element() [%s] remove fail", ename);
                        g_free (ename);
                        return FALSE;
-               } else
-                       gst_object_unref (parent);
+               } else {
+                       gst_object_unref(parent);
+               }
        } else {
                gst_object_unref(element);
        }
+
        return TRUE;
   }
 
-static gboolean 
+static gboolean
 gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
 {
        GstPad *srcpad = NULL, *sinkpad = NULL;
        switch(encodebin->profile) {
                case GST_ENCODE_BIN_PROFILE_AV :
-                       if(!gst_caps_is_any(encodebin->vcaps))
-                       {
+                       if (!gst_caps_is_any(encodebin->vcaps)) {
+                               gchar *caps_str = NULL;
+                               caps_str = gst_caps_to_string(encodebin->vcaps);
+                               if (caps_str) {
+                                       GST_INFO_OBJECT(encodebin, "vconv caps [%s]", caps_str);
+                                       g_free(caps_str);
+                                       caps_str = NULL;
+                               }
+
                                g_object_set(encodebin->vcapsfilter, "caps", encodebin->vcaps, NULL);
                        }
-       
+
                        if (encodebin->auto_color_space) {
                                if(encodebin->color_space == NULL) {
-                                   encodebin->color_space  = gst_element_factory_make ("ffmpegcolorspace","color_space");
-                                   gst_bin_add (GST_BIN (encodebin), encodebin->color_space);
+                                       encodebin->color_space = gst_element_factory_make (encodebin->vconv_name, "video_convert");
+                                       gst_bin_add (GST_BIN (encodebin), encodebin->color_space);
                                }
-                               
-                               srcpad = gst_element_get_static_pad(encodebin->video_queue, "src");                             
+
+                               srcpad = gst_element_get_static_pad(encodebin->video_queue, "src");
                                if( encodebin->video_toggle )
                                {
                                        sinkpad = gst_element_get_static_pad(encodebin->video_toggle, "sink");
                                        _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
-                                       
+
                                        srcpad = gst_element_get_static_pad(encodebin->video_toggle, "src");
                                }
                                sinkpad = gst_element_get_static_pad(encodebin->color_space, "sink");
@@ -1877,100 +1977,100 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
 
                                srcpad = gst_element_get_static_pad(encodebin->color_space, "src");
                                sinkpad = gst_element_get_static_pad(encodebin->vcapsfilter, "sink");
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
 
                                srcpad = gst_element_get_static_pad(encodebin->vcapsfilter, "src");
                                sinkpad = gst_element_get_static_pad(encodebin->video_encode, "sink");
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);                                  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
 #if 0
                                if(encodebin->use_venc_queue)
                                {
                                        if(encodebin->video_encode_queue == NULL) {
                                            encodebin->video_encode_queue  = gst_element_factory_make ("queue","video_encode_queue");
                                            gst_bin_add (GST_BIN (encodebin), encodebin->video_encode_queue);
-                                               
+
                                            ENCODER_QUEUE_SET(encodebin->video_encode_queue, 0, 0, VIDEO_ENC_QUE_TIME);
-                                           encodebin->veque_sig_id = g_signal_connect( G_OBJECT(encodebin->video_encode_queue), "overrun", 
+                                           encodebin->veque_sig_id = g_signal_connect( G_OBJECT(encodebin->video_encode_queue), "overrun",
                                                                                                                                G_CALLBACK(queue_overun_cb), encodebin);
-                                                       
-                                       }       
+
+                                       }
 
                                        srcpad = gst_element_get_static_pad(encodebin->video_encode, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->video_encode_queue, "sink");
-                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);  
+                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
                                }
 #else
                                if(encodebin->video_encode_queue)
                                {
                                    ENCODER_QUEUE_SET(encodebin->video_encode_queue, 0, 0, VIDEO_ENC_QUE_TIME);
-                                   encodebin->veque_sig_id = g_signal_connect( G_OBJECT(encodebin->video_encode_queue), "overrun", 
+                                   encodebin->veque_sig_id = g_signal_connect( G_OBJECT(encodebin->video_encode_queue), "overrun",
                                                                                                                                G_CALLBACK(queue_overun_cb), encodebin);
 #if 0
-                                   g_object_set(G_OBJECT(encodebin->video_queue), 
-                                               "max-size-bytes", (guint)0, 
-                                               "max-size-buffers", (guint)1,   
-                                               "max-size-time", (guint64)0, 
-                                               NULL); 
+                                   g_object_set(G_OBJECT(encodebin->video_queue),
+                                               "max-size-bytes", (guint)0,
+                                               "max-size-buffers", (guint)1,
+                                               "max-size-time", (guint64)0,
+                                               NULL);
 #endif
                                        srcpad = gst_element_get_static_pad(encodebin->video_encode, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->video_encode_queue, "sink");
-                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);  
+                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
                                }
 #endif
-                                                                
+
                        }
                        else {
                                srcpad = gst_element_get_static_pad(encodebin->video_queue, "src");
                                if( encodebin->video_toggle )
                                {
                                        sinkpad = gst_element_get_static_pad(encodebin->video_toggle, "sink");
-                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);  
+                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
 
                                        srcpad = gst_element_get_static_pad(encodebin->video_toggle, "src");
                                }
                                sinkpad = gst_element_get_static_pad(encodebin->vcapsfilter, "sink");
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
 
                                srcpad = gst_element_get_static_pad(encodebin->vcapsfilter, "src");
                                sinkpad = gst_element_get_static_pad(encodebin->video_encode, "sink");
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);                                  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
  #if 0
                                if(encodebin->use_venc_queue)
                                {
                                        if(encodebin->video_encode_queue == NULL) {
                                            encodebin->video_encode_queue  = gst_element_factory_make ("queue","video_encode_queue");
                                            gst_bin_add (GST_BIN (encodebin), encodebin->video_encode_queue);
-                                               
+
                                            ENCODER_QUEUE_SET(encodebin->video_encode_queue, 0, 0, VIDEO_ENC_QUE_TIME);
-                                           encodebin->veque_sig_id = g_signal_connect( G_OBJECT(encodebin->video_encode_queue), "overrun", 
-                                                                                                                               G_CALLBACK(queue_overun_cb), encodebin);                                                        
+                                           encodebin->veque_sig_id = g_signal_connect( G_OBJECT(encodebin->video_encode_queue), "overrun",
+                                                                                                                               G_CALLBACK(queue_overun_cb), encodebin);
                                        }
-                                       
+
                                        srcpad = gst_element_get_static_pad(encodebin->video_encode, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->video_encode_queue, "sink");
                                        _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
-                                       
-                               }                       
+
+                               }
 #else
                                if(encodebin->video_encode_queue)
                                {
                                    ENCODER_QUEUE_SET(encodebin->video_encode_queue, 0, 0, VIDEO_ENC_QUE_TIME);
-                                   encodebin->veque_sig_id = g_signal_connect( G_OBJECT(encodebin->video_encode_queue), "overrun", 
+                                   encodebin->veque_sig_id = g_signal_connect( G_OBJECT(encodebin->video_encode_queue), "overrun",
                                                                                                                                G_CALLBACK(queue_overun_cb), encodebin);
-#if 0                                  
-                                   g_object_set(G_OBJECT(encodebin->video_queue), 
-                                               "max-size-bytes", (guint)0, 
-                                               "max-size-buffers", (guint)1,   
-                                               "max-size-time", (guint64)0, 
-                                               NULL);                                  
+#if 0
+                                   g_object_set(G_OBJECT(encodebin->video_queue),
+                                               "max-size-bytes", (guint)0,
+                                               "max-size-buffers", (guint)1,
+                                               "max-size-time", (guint64)0,
+                                               NULL);
 #endif
 
                                        srcpad = gst_element_get_static_pad(encodebin->video_encode, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->video_encode_queue, "sink");
-                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);  
+                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
                                }
-#endif                         
-               
+#endif
+
                        }
 
 //                     gst_element_get_request_pad (encodebin->mux, "video_%d");
@@ -1979,45 +2079,45 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
                        {
                                srcpad = gst_element_get_static_pad(encodebin->video_encode_queue, "src");
                                sinkpad = encodebin->mux_video_sinkpad = gst_encode_bin_get_mux_sink_pad(encodebin->mux, ENCODEBIN_MUX_VIDEO_SINK);
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);                          
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
                        }
 #else
                        if(encodebin->video_encode_queue)
                        {
                                srcpad = gst_element_get_static_pad(encodebin->video_encode_queue, "src");
                                sinkpad = encodebin->mux_video_sinkpad = gst_encode_bin_get_mux_sink_pad(encodebin->mux, ENCODEBIN_MUX_VIDEO_SINK);
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);                          
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
                        }
 #endif
                        else
                        {
                                srcpad = gst_element_get_static_pad(encodebin->video_encode, "src");
                                sinkpad = encodebin->mux_video_sinkpad = gst_encode_bin_get_mux_sink_pad(encodebin->mux, ENCODEBIN_MUX_VIDEO_SINK);
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);                  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, video_link_fail);
                        }
 
                        srcpad = gst_element_get_static_pad(encodebin->mux, "src");
                        if(gst_ghost_pad_get_target(GST_GHOST_PAD (encodebin->srcpad)) != srcpad)
                                gst_ghost_pad_set_target(GST_GHOST_PAD (encodebin->srcpad), srcpad);
                        gst_object_unref(srcpad);
-                       srcpad = NULL;                  
-               
+                       srcpad = NULL;
+
                        /* For pause/resume control */
 //                     encodebin->vsink_probeid = gst_pad_add_data_probe (gst_element_get_static_pad (encodebin->video_queue, "sink"),
                        sinkpad = gst_element_get_static_pad (encodebin->video_queue, "sink");
                        encodebin->vsink_probeid = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (gst_encode_bin_video_probe), encodebin);
                        gst_object_unref(sinkpad);
                        sinkpad = NULL;
-    
+
                        if(encodebin->high_speed_fps > DEFAULT_PROP_HIGH_SPEED)
                        {
 //                             encodebin->vsink_hs_probeid = gst_pad_add_data_probe (gst_element_get_static_pad (encodebin->video_encode, "sink"),
                                sinkpad = gst_element_get_static_pad (encodebin->video_encode, "sink");
                                encodebin->vsink_hs_probeid = gst_pad_add_buffer_probe (sinkpad,        G_CALLBACK (gst_encode_bin_video_probe_hs), encodebin);
                                gst_object_unref(sinkpad);
-                               sinkpad = NULL;                         
-                       }                       
-                       
+                               sinkpad = NULL;
+                       }
+
                        if(encodebin->audio_queue == NULL)
                        {
                                GST_WARNING_OBJECT(encodebin, "Audio pad isn't requested, recording video only mode");
@@ -2025,7 +2125,7 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
                        }
                case GST_ENCODE_BIN_PROFILE_AUDIO :
                        if(!gst_caps_is_any(encodebin->acaps))
-                       {                       
+                       {
                                g_object_set(encodebin->acapsfilter, "caps", encodebin->acaps, NULL);
                        }
                        if (encodebin->auto_audio_convert ||encodebin->auto_audio_resample) {
@@ -2044,42 +2144,42 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
 
                                        srcpad = gst_element_get_static_pad(encodebin->acapsfilter, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->audio_encode, "sink");
-                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);                                  
-#if 0                                  
+                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
+#if 0
                                        if(encodebin->use_aenc_queue)
                                        {
                                                if(encodebin->audio_encode_queue == NULL) {
                                                    encodebin->audio_encode_queue  = gst_element_factory_make ("queue","audio_encode_queue");
                                                    gst_bin_add (GST_BIN (encodebin), encodebin->audio_encode_queue);
-                                                 
+
                                                   ENCODER_QUEUE_SET(encodebin->audio_encode_queue, 0, 0, AUDIO_ENC_QUE_TIME);
-                                                  encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun", 
-                                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);                                           
-                                               }       
+                                                  encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun",
+                                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);
+                                               }
 
                                                srcpad = gst_element_get_static_pad(encodebin->audio_encode, "src");
                                                sinkpad = gst_element_get_static_pad(encodebin->audio_encode_queue, "sink");
-                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);  
-                                       }                                       
+                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
+                                       }
 #else
                                        if(encodebin->audio_encode_queue)
                                        {
-                                 
+
                                                ENCODER_QUEUE_SET(encodebin->audio_encode_queue, 0, 0, AUDIO_ENC_QUE_TIME);
-                                               encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun", 
-                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);                                           
+                                               encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun",
+                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);
 
                                                srcpad = gst_element_get_static_pad(encodebin->audio_encode, "src");
                                                sinkpad = gst_element_get_static_pad(encodebin->audio_encode_queue, "sink");
-                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);  
+                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
                                        }
 #endif
-                                       
+
                                } else if (!encodebin->auto_audio_resample) {
                                          if (encodebin->audio_conv == NULL) {
                                                encodebin->audio_conv = gst_element_factory_make ("audioconvert","audio_conv");
                                              gst_bin_add (GST_BIN (encodebin), encodebin->audio_conv);
-                                          }    
+                                          }
 
                                        srcpad = gst_element_get_static_pad(encodebin->audio_queue, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->audio_conv, "sink");
@@ -2091,8 +2191,8 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
 
                                        srcpad = gst_element_get_static_pad(encodebin->acapsfilter, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->audio_encode, "sink");
-                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);                                  
-#if 0                                  
+                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
+#if 0
                                        if(encodebin->use_aenc_queue)
                                        {
                                                if(encodebin->audio_encode_queue == NULL) {
@@ -2100,29 +2200,29 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
                                                    gst_bin_add (GST_BIN (encodebin), encodebin->audio_encode_queue);
 
                                                    ENCODER_QUEUE_SET(encodebin->audio_encode_queue, 0, 0, AUDIO_ENC_QUE_TIME);
-                                                  encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun", 
-                                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);                                                        
+                                                  encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun",
+                                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);
                                                }
 
                                                srcpad = gst_element_get_static_pad(encodebin->audio_encode, "src");
                                                sinkpad = gst_element_get_static_pad(encodebin->audio_encode_queue, "sink");
-                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);                                          
-                               
-                                       }                                       
+                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
+
+                                       }
 #else
                                        if(encodebin->audio_encode_queue)
                                        {
-                                 
+
                                                ENCODER_QUEUE_SET(encodebin->audio_encode_queue, 0, 0, AUDIO_ENC_QUE_TIME);
-                                               encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun", 
-                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);                                           
+                                               encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun",
+                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);
 
                                                srcpad = gst_element_get_static_pad(encodebin->audio_encode, "src");
                                                sinkpad = gst_element_get_static_pad(encodebin->audio_encode_queue, "sink");
-                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);  
+                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
                                        }
-#endif                                 
-                                       
+#endif
+
                                } else {
                                        if(encodebin->audio_sample == NULL) {
                                                encodebin->audio_sample = gst_element_factory_make ("audioresample","audio_sample");
@@ -2135,7 +2235,7 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
 
                                        srcpad = gst_element_get_static_pad(encodebin->audio_queue, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->audio_conv, "sink");
-                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);  
+                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
 
                                        srcpad = gst_element_get_static_pad(encodebin->audio_conv, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->audio_sample, "sink");
@@ -2143,89 +2243,89 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
 
                                        srcpad = gst_element_get_static_pad(encodebin->audio_sample, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->acapsfilter, "sink");
-                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);                                          
+                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
 
                                        srcpad = gst_element_get_static_pad(encodebin->acapsfilter, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->audio_encode, "sink");
-                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);  
-#if 0                                  
+                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
+#if 0
                                        if(encodebin->use_aenc_queue)
                                        {
                                                if(encodebin->audio_encode_queue == NULL) {
                                                    encodebin->audio_encode_queue  = gst_element_factory_make ("queue","audio_encode_queue");
                                                    gst_bin_add (GST_BIN (encodebin), encodebin->audio_encode_queue);
-                                                       
+
                                                    ENCODER_QUEUE_SET(encodebin->audio_encode_queue, 0, 0, AUDIO_ENC_QUE_TIME);
-                                                  encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun", 
-                                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);                                                
-                                               }       
+                                                  encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun",
+                                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);
+                                               }
 
                                                srcpad = gst_element_get_static_pad(encodebin->audio_encode, "src");
                                                sinkpad = gst_element_get_static_pad(encodebin->audio_encode_queue, "sink");
                                                _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
-                                       
-                                       }                       
+
+                                       }
 #else
                                        if(encodebin->audio_encode_queue)
                                        {
-                                 
+
                                                ENCODER_QUEUE_SET(encodebin->audio_encode_queue, 0, 0, AUDIO_ENC_QUE_TIME);
-                                               encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun", 
-                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);                                           
+                                               encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun",
+                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);
 
                                                srcpad = gst_element_get_static_pad(encodebin->audio_encode, "src");
                                                sinkpad = gst_element_get_static_pad(encodebin->audio_encode_queue, "sink");
-                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);  
+                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
                                        }
-#endif                                 
-                                       
+#endif
+
                                }
                        }else {
 
                                srcpad = gst_element_get_static_pad(encodebin->audio_queue, "src");
                                sinkpad = gst_element_get_static_pad(encodebin->acapsfilter, "sink");
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);                  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
 
                                srcpad = gst_element_get_static_pad(encodebin->acapsfilter, "src");
                                sinkpad = gst_element_get_static_pad(encodebin->audio_encode, "sink");
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);                                  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
 #if 0
                                if(encodebin->use_aenc_queue)
                                {
                                        if(encodebin->audio_encode_queue == NULL) {
                                            encodebin->audio_encode_queue  = gst_element_factory_make ("queue","audio_encode_queue");
                                            gst_bin_add (GST_BIN (encodebin), encodebin->audio_encode_queue);
-                                               
+
                                            ENCODER_QUEUE_SET(encodebin->audio_encode_queue, 0, 0, AUDIO_ENC_QUE_TIME);
-                                          encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun", 
-                                                                                                                               G_CALLBACK(queue_overun_cb), encodebin);                                
-                                       }               
+                                          encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun",
+                                                                                                                               G_CALLBACK(queue_overun_cb), encodebin);
+                                       }
 
                                        srcpad = gst_element_get_static_pad(encodebin->audio_encode, "src");
                                        sinkpad = gst_element_get_static_pad(encodebin->audio_encode_queue, "sink");
-                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);                                  
-                               }                               
+                                       _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
+                               }
 #else
                                        if(encodebin->audio_encode_queue)
                                        {
-                                 
+
                                                ENCODER_QUEUE_SET(encodebin->audio_encode_queue, 0, 0, AUDIO_ENC_QUE_TIME);
-                                               encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun", 
-                                                                                                                       G_CALLBACK(queue_overun_cb), encodebin);                                           
+                        encodebin->aeque_sig_id = g_signal_connect( G_OBJECT(encodebin->audio_encode_queue), "overrun",
+                                                                    G_CALLBACK(queue_overun_cb), encodebin);
 
                                                srcpad = gst_element_get_static_pad(encodebin->audio_encode, "src");
                                                sinkpad = gst_element_get_static_pad(encodebin->audio_encode_queue, "sink");
-                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);  
+                                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
                                        }
-#endif                                 
-                               
+#endif
+
                        }
-#if 0                  
+#if 0
                        if(encodebin->use_aenc_queue)
                        {
                                srcpad = gst_element_get_static_pad(encodebin->audio_encode_queue, "src");
                                sinkpad = encodebin->mux_audio_sinkpad = gst_encode_bin_get_mux_sink_pad(encodebin->mux, ENCODEBIN_MUX_AUDIO_SINK);
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
 
                        }
 #else
@@ -2234,16 +2334,16 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
                        {
                                srcpad = gst_element_get_static_pad(encodebin->audio_encode_queue, "src");
                                sinkpad = encodebin->mux_audio_sinkpad = gst_encode_bin_get_mux_sink_pad(encodebin->mux, ENCODEBIN_MUX_AUDIO_SINK);
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
 
                        }
 #endif
                        else
-                       {       
+                       {
                                srcpad = gst_element_get_static_pad(encodebin->audio_encode, "src");
                                sinkpad = encodebin->mux_audio_sinkpad = gst_encode_bin_get_mux_sink_pad(encodebin->mux, ENCODEBIN_MUX_AUDIO_SINK);
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, audio_link_fail);
+
                        }
 
                        srcpad = gst_element_get_static_pad(encodebin->mux, "src");
@@ -2261,10 +2361,10 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
                        break;
                case GST_ENCODE_BIN_PROFILE_IMAGE :
                        if(!gst_caps_is_any(encodebin->icaps))
-                       {                               
+                       {
                                g_object_set(encodebin->icapsfilter, "caps", encodebin->icaps, NULL);
                        }
-                               
+
                        if (encodebin->auto_color_space) {
                                if(encodebin->color_space == NULL) {
                                    encodebin->color_space  = gst_element_factory_make ("ffmpegcolorspace","color_space");
@@ -2277,30 +2377,30 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
 
                                srcpad = gst_element_get_static_pad(encodebin->image_toggle, "src");
                                sinkpad = gst_element_get_static_pad(encodebin->color_space, "sink");
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, image_link_fail);          
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, image_link_fail);
 
                                srcpad = gst_element_get_static_pad(encodebin->color_space, "src");
                                sinkpad = gst_element_get_static_pad(encodebin->icapsfilter, "sink");
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, image_link_fail);  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, image_link_fail);
 
                                srcpad = gst_element_get_static_pad(encodebin->icapsfilter, "src");
                                sinkpad = gst_element_get_static_pad(encodebin->image_encode, "sink");
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, image_link_fail);                                  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, image_link_fail);
 
                        }
                        else {
-                               
+
                                srcpad = gst_element_get_static_pad(encodebin->image_queue, "src");
                                sinkpad = gst_element_get_static_pad(encodebin->image_toggle, "sink");
                                _GST_PAD_LINK_UNREF(srcpad, sinkpad, image_link_fail);
 
                                srcpad = gst_element_get_static_pad(encodebin->image_toggle, "src");
                                sinkpad = gst_element_get_static_pad(encodebin->icapsfilter, "sink");
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, image_link_fail);          
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, image_link_fail);
 
                                srcpad = gst_element_get_static_pad(encodebin->icapsfilter, "src");
                                sinkpad = gst_element_get_static_pad(encodebin->image_encode, "sink");
-                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, image_link_fail);                                  
+                               _GST_PAD_LINK_UNREF(srcpad, sinkpad, image_link_fail);
 
                        }
                        srcpad =  gst_element_get_static_pad (encodebin->image_encode, "src");
@@ -2314,7 +2414,7 @@ gst_encode_bin_link_elements (GstEncodeBin *encodebin)  // need to return ????
                      return FALSE;
                      break;
        }
-//     gst_pad_set_active(encodebin->srcpad, TRUE);    
+//     gst_pad_set_active(encodebin->srcpad, TRUE);
        return TRUE;
 
 video_link_fail:
@@ -2322,78 +2422,71 @@ video_link_fail:
        gst_encode_bin_remove_element(encodebin, encodebin->color_space);
        GST_WARNING_OBJECT(encodebin, "encodebin link video elements fail");
        return FALSE;
-       
+
 audio_link_fail:
-       // remove element 
-       gst_encode_bin_remove_element(encodebin, encodebin->audio_conv);        
-       gst_encode_bin_remove_element(encodebin, encodebin->audio_sample);      
+       // remove element
+       gst_encode_bin_remove_element(encodebin, encodebin->audio_conv);
+       gst_encode_bin_remove_element(encodebin, encodebin->audio_sample);
        GST_WARNING_OBJECT(encodebin, "encodebin link audio elements fail");
        return FALSE;
 
 image_link_fail:
-       // remove element 
-       gst_encode_bin_remove_element(encodebin, encodebin->color_space);       
+       // remove element
+       gst_encode_bin_remove_element(encodebin, encodebin->color_space);
        GST_WARNING_OBJECT(encodebin, "encodebin link image elements fail");
        return FALSE;
 
-       
+
 }
 
-static gboolean 
+static gboolean
 gst_encode_bin_unlink_elements (GstEncodeBin *encodebin)
 {
        GstPad *pad = NULL, *muxpad = NULL;
-       
+
        switch(encodebin->profile) {
                case GST_ENCODE_BIN_PROFILE_AV :
                        if (encodebin->auto_color_space) {
-                               if( encodebin->video_toggle )
-                               {
-                                       gst_element_unlink_many  (
+                               if (encodebin->video_toggle) {
+                                       gst_element_unlink_many(
                                                encodebin->video_queue,
                                                encodebin->video_toggle,
                                                encodebin->color_space,
-                                               encodebin->vcapsfilter,                                                         
+                                               encodebin->vcapsfilter,
                                                encodebin->video_encode,
-                                               //encodebin->video_encode_queue,                                        
+                                               //encodebin->video_encode_queue,
                                                NULL);
-                               }
-                               else
-                               {
+                               } else {
                                        gst_element_unlink_many(
                                                encodebin->video_queue,
                                                encodebin->color_space,
-                                               encodebin->vcapsfilter,                                                         
+                                               encodebin->vcapsfilter,
                                                encodebin->video_encode,
-                                               //encodebin->video_encode_queue,                                        
+                                               //encodebin->video_encode_queue,
                                                NULL);
                                }
-                       }
-                       else {
-                               if( encodebin->video_toggle )
-                               {
-                                       gst_element_unlink_many  (
+                       } else {
+                               if (encodebin->video_toggle) {
+                                       gst_element_unlink_many(
                                                encodebin->video_queue,
                                                encodebin->video_toggle,
-                                               encodebin->vcapsfilter,                                                         
+                                               encodebin->vcapsfilter,
                                                encodebin->video_encode,
-                                               //encodebin->video_encode_queue,                                                
+                                               //encodebin->video_encode_queue,
                                                NULL);
-                               }
-                               else
-                               {
+                               } else {
                                        gst_element_unlink_many(
                                                encodebin->video_queue,
-                                               encodebin->vcapsfilter,                                                         
+                                               encodebin->vcapsfilter,
                                                encodebin->video_encode,
-                                               //encodebin->video_encode_queue,                                                
+                                               //encodebin->video_encode_queue,
                                                NULL);
                                }
                        }
 
                        if(encodebin->mux_video_sinkpad != NULL)
                        {
-#if 0                  
+#if 0
                                if(encodebin->use_venc_queue)
                                {
                                        gst_element_unlink(encodebin->video_encode, encodebin->video_encode_queue);
@@ -2443,9 +2536,9 @@ gst_encode_bin_unlink_elements (GstEncodeBin *encodebin)
                                gst_pad_remove_buffer_probe(pad, encodebin->vsink_probeid);
                                encodebin->vsink_probeid = 0;
                                gst_object_unref(pad);
-                               pad = NULL;                                     
+                               pad = NULL;
                        }
-               
+
 
                        if(encodebin->vsink_hs_probeid)
                        {
@@ -2468,22 +2561,22 @@ gst_encode_bin_unlink_elements (GstEncodeBin *encodebin)
                                                        encodebin->audio_sample,
                                                        encodebin->acapsfilter,
                                                        encodebin->audio_encode,
-                                                       NULL);  
+                                                       NULL);
                                } else if (!encodebin->auto_audio_resample) {
                                                gst_element_unlink_many  (
                                                        encodebin->audio_queue,
-                                                       encodebin->audio_conv,                                  
+                                                       encodebin->audio_conv,
                                                        encodebin->acapsfilter,
                                                        encodebin->audio_encode,
-                                                       NULL);  
+                                                       NULL);
                                } else {
                                                gst_element_unlink_many  (
                                                        encodebin->audio_queue,
                                                        encodebin->audio_conv,
-                                                       encodebin->audio_sample,                                                                                
+                                                       encodebin->audio_sample,
                                                        encodebin->acapsfilter,
                                                        encodebin->audio_encode,
-                                                       NULL);                                  
+                                                       NULL);
                                }
                        }
                        else {
@@ -2491,12 +2584,12 @@ gst_encode_bin_unlink_elements (GstEncodeBin *encodebin)
                                        encodebin->audio_queue,
                                        encodebin->acapsfilter,
                                        encodebin->audio_encode,
-                                       NULL);  
+                                       NULL);
                        }
 
                        if(encodebin->mux_audio_sinkpad != NULL)
                        {
-#if 0                  
+#if 0
                                if(encodebin->use_aenc_queue)
                                {
                                        gst_element_unlink(encodebin->audio_encode, encodebin->audio_encode_queue);
@@ -2504,12 +2597,12 @@ gst_encode_bin_unlink_elements (GstEncodeBin *encodebin)
                                        pad = gst_element_get_static_pad (encodebin->audio_encode_queue, "src");
                                        gst_pad_unlink(pad, muxpad);
                                        gst_object_unref(pad);
-                                       pad = NULL;     
+                                       pad = NULL;
 
                                        if ( g_signal_handler_is_connected ( encodebin->audio_encode_queue, encodebin->veque_sig_id) )
                                        {
                                                g_signal_handler_disconnect (  encodebin->audio_encode_queue, encodebin->veque_sig_id );
-                                       }                                       
+                                       }
                                }
 #else
                                if(encodebin->audio_encode_queue)
@@ -2519,12 +2612,12 @@ gst_encode_bin_unlink_elements (GstEncodeBin *encodebin)
                                        pad = gst_element_get_static_pad (encodebin->audio_encode_queue, "src");
                                        gst_pad_unlink(pad, encodebin->mux_audio_sinkpad);
                                        gst_object_unref(pad);
-                                       pad = NULL;     
+                                       pad = NULL;
 
                                        if ( g_signal_handler_is_connected ( encodebin->audio_encode_queue, encodebin->veque_sig_id) )
                                        {
                                                g_signal_handler_disconnect (  encodebin->audio_encode_queue, encodebin->veque_sig_id );
-                                       }                                       
+                                       }
                                }
 #endif
                                else
@@ -2533,7 +2626,7 @@ gst_encode_bin_unlink_elements (GstEncodeBin *encodebin)
                                        gst_pad_unlink(pad, encodebin->mux_audio_sinkpad);
                                        gst_object_unref(pad);
                                        pad = NULL;
-                               }                       
+                               }
 
                                gst_element_release_request_pad(encodebin->mux, encodebin->mux_audio_sinkpad);
 //                             gst_object_unref(encodebin->mux_audio_sinkpad);         //***
@@ -2542,7 +2635,7 @@ gst_encode_bin_unlink_elements (GstEncodeBin *encodebin)
 
                        if(encodebin->asink_probeid)
                        {
-                               pad = gst_element_get_static_pad (encodebin->audio_queue, "sink"); 
+                               pad = gst_element_get_static_pad (encodebin->audio_queue, "sink");
                                gst_pad_remove_buffer_probe(pad, encodebin->asink_probeid);
                                encodebin->asink_probeid =0;
                                gst_object_unref(pad);
@@ -2556,17 +2649,17 @@ gst_encode_bin_unlink_elements (GstEncodeBin *encodebin)
                                        encodebin->image_queue,
                                        encodebin->image_toggle,
                                        encodebin->color_space,
-                                       encodebin->icapsfilter,                                                         
+                                       encodebin->icapsfilter,
                                        encodebin->image_encode,
                                        NULL);
                        }
                        else {
                                gst_element_unlink_many  (
                                        encodebin->image_queue,
-                                       encodebin->image_toggle,        
-                                       encodebin->icapsfilter,                                                                                                                         
+                                       encodebin->image_toggle,
+                                       encodebin->icapsfilter,
                                        encodebin->image_encode,
-                                       NULL);  
+                                       NULL);
                        }
                        break;
                default:
@@ -2574,12 +2667,12 @@ gst_encode_bin_unlink_elements (GstEncodeBin *encodebin)
                          return FALSE;
                  break;
        }
-       //      gst_pad_set_active(encodebin->srcpad, TRUE);    
+       //      gst_pad_set_active(encodebin->srcpad, TRUE);
        return TRUE;
 
 }
 
-static gboolean 
+static gboolean
 gst_encode_bin_init_video_elements (GstElement *element, gpointer user_data)
 {
        GstEncodeBin *encodebin = GST_ENCODE_BIN (element);
@@ -2609,18 +2702,18 @@ gst_encode_bin_init_video_elements (GstElement *element, gpointer user_data)
        if(encodebin->vcapsfilter == NULL) {
                encodebin->vcapsfilter = gst_element_factory_make ("capsfilter","vcapsfilter");
                gst_bin_add (GST_BIN (element), encodebin->vcapsfilter);
-       }  
+       }
 #if 0
        encodebin->vcaps = gst_caps_new_simple("video/x-raw-yuv",
                "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
                "width", G_TYPE_INT, 320,
                "height", G_TYPE_INT, 240,
                "framerate", GST_TYPE_FRACTION, 30, 1,
-               NULL);  
+               NULL);
 
 #endif
        if(encodebin->video_encode == NULL) {
-               encodebin->video_encode = gst_element_factory_make (encodebin->venc_name, "video_encode");
+               encodebin->video_encode = gst_element_factory_make (encodebin->venc_name, NULL);
                gst_bin_add (GST_BIN (element), encodebin->video_encode);
        }
 
@@ -2638,33 +2731,33 @@ gst_encode_bin_init_video_elements (GstElement *element, gpointer user_data)
                gst_bin_add (GST_BIN (element), encodebin->mux);
        }
 
-       if (!encodebin->video_encode 
-//             || !encodebin->video_encode_queue 
-               || !encodebin->mux 
-               || !encodebin->video_queue 
+       if (!encodebin->video_encode
+//             || !encodebin->video_encode_queue
+               || !encodebin->mux
+               || !encodebin->video_queue
                || !encodebin->vcapsfilter
                || !encodebin->srcpad )
        {
                GST_ERROR_OBJECT(encodebin, "Faild create element \n");
                return FALSE;
        }
-       
+
        if( encodebin->use_video_toggle && !encodebin->video_toggle )
        {
                GST_ERROR_OBJECT(encodebin, "Faild create video toggle element \n");
                return FALSE;
        }
 
-#if 0  
+#if 0
   if (encodebin->auto_color_space && (encodebin->color_space == NULL)) {
        encodebin->color_space = gst_element_factory_make ("ffmpegcolorspace","color_space");
       gst_bin_add (GST_BIN (element), encodebin->color_space);
-   }  
-#endif  
+   }
+#endif
   return TRUE;
 }
 
-static gboolean 
+static gboolean
 gst_encode_bin_init_audio_elements (GstElement *element, gpointer user_data)
 {
        GstEncodeBin *encodebin = GST_ENCODE_BIN (element);
@@ -2680,7 +2773,7 @@ gst_encode_bin_init_audio_elements (GstElement *element, gpointer user_data)
        if(encodebin->acapsfilter == NULL) {
                encodebin->acapsfilter = gst_element_factory_make ("capsfilter","acapsfilter");
                gst_bin_add (GST_BIN (element), encodebin->acapsfilter);
-       }    
+       }
 #if 0
 encodebin->acaps = gst_caps_new_simple("audio/x-raw-int",
        "rate", G_TYPE_INT, 8000,
@@ -2699,10 +2792,10 @@ encodebin->acaps = gst_caps_new_simple("audio/x-raw-int",
                gst_bin_add (GST_BIN (element), encodebin->mux);
        }
 
-       if (!encodebin->audio_encode 
+       if (!encodebin->audio_encode
                || !encodebin->audio_queue
                || !encodebin->mux
-               || !encodebin->acapsfilter      
+               || !encodebin->acapsfilter
                || !encodebin->srcpad )
        {
                GST_ERROR_OBJECT(encodebin, "Faild create element \n");
@@ -2712,18 +2805,18 @@ encodebin->acaps = gst_caps_new_simple("audio/x-raw-int",
        if (encodebin->auto_audio_convert && (encodebin->audio_conv == NULL)) {
                encodebin->audio_conv = gst_element_factory_make ("audioconvert","audio_conv");
                gst_bin_add (GST_BIN (element), encodebin->audio_conv);
-       } 
+       }
 
        if (encodebin->auto_audio_resample && (encodebin->audio_sample == NULL)) {
                encodebin->audio_sample = gst_element_factory_make ("audioresample","audio_sample");
                gst_bin_add (GST_BIN (element), encodebin->audio_sample);
-       } 
+       }
 #endif
        return TRUE;
 }
 
 
-static gboolean 
+static gboolean
 gst_encode_bin_init_image_elements (GstElement *element, gpointer user_data)
 {
        GstEncodeBin *encodebin = GST_ENCODE_BIN (element);
@@ -2744,14 +2837,14 @@ gst_encode_bin_init_image_elements (GstElement *element, gpointer user_data)
        if(encodebin->icapsfilter == NULL) {
                encodebin->icapsfilter = gst_element_factory_make ("capsfilter","icapsfilter");
                gst_bin_add (GST_BIN (element), encodebin->icapsfilter);
-       }  
+       }
 
        if(encodebin->image_encode == NULL) {
                encodebin->image_encode = gst_element_factory_make (encodebin->ienc_name, "image_encode");
                gst_bin_add (GST_BIN (element), encodebin->image_encode);
-       }  
+       }
 
-       if (!encodebin->image_encode 
+       if (!encodebin->image_encode
                || !encodebin->image_queue
                || !encodebin->image_toggle
                || !encodebin->icapsfilter
@@ -2764,21 +2857,21 @@ gst_encode_bin_init_image_elements (GstElement *element, gpointer user_data)
        if (encodebin->auto_color_space && (encodebin->color_space == NULL)) {
                encodebin->color_space = gst_element_factory_make ("ffmpegcolorspace","color_space");
                gst_bin_add (GST_BIN (element), encodebin->color_space);
-       }  
+       }
 #endif
        return TRUE;
 }
 
 static gboolean gst_encode_bin_block(GstEncodeBin *encodebin, gboolean value)
 {
-  
+
        if(value) { //block stream
                switch(encodebin->profile) {
                        case GST_ENCODE_BIN_PROFILE_AV:
                                if(encodebin->audio_queue == NULL && encodebin->video_queue == NULL) {
                                        goto block_fail;
                                } else {
-                                       if(g_object_class_find_property(G_OBJECT_GET_CLASS(GST_OBJECT(encodebin->video_queue)), 
+                                       if(g_object_class_find_property(G_OBJECT_GET_CLASS(GST_OBJECT(encodebin->video_queue)),
                                                "empty-buffers") == NULL) {
                                                GST_ERROR_OBJECT(encodebin, "The queue element doesn't support 'empty-buffers' property");
                                                goto block_fail;
@@ -2788,7 +2881,7 @@ static gboolean gst_encode_bin_block(GstEncodeBin *encodebin, gboolean value)
                                                g_object_set(encodebin->video_toggle, "block-data", TRUE , NULL);
                                                GST_INFO_OBJECT( encodebin, "video_toggle block-data TRUE" );
                                        }
-                                       
+
                                        g_object_set(encodebin->video_queue, "empty-buffers", TRUE , NULL);
                                        GST_INFO_OBJECT( encodebin, "video_queue empty-buffers TRUE" );
                                        if(encodebin->audio_queue != NULL)
@@ -2800,13 +2893,13 @@ static gboolean gst_encode_bin_block(GstEncodeBin *encodebin, gboolean value)
                                break;
                        case GST_ENCODE_BIN_PROFILE_AUDIO:
                                if(encodebin->audio_queue == NULL) {
-                                       goto block_fail;                                        
+                                       goto block_fail;
                                } else {
-                                       if(g_object_class_find_property(G_OBJECT_GET_CLASS(GST_OBJECT(encodebin->audio_queue)), 
+                                       if(g_object_class_find_property(G_OBJECT_GET_CLASS(GST_OBJECT(encodebin->audio_queue)),
                                                "empty-buffers") == NULL) {
                                                GST_ERROR_OBJECT(encodebin, "The queue element doesn't support 'empty-buffers' property");
                                                goto block_fail;
-                                       }                               
+                                       }
                                        g_object_set(encodebin->audio_queue, "empty-buffers", TRUE , NULL);
                                        GST_INFO_OBJECT( encodebin, "audio_queue empty-buffers TRUE" );
                                }
@@ -2818,11 +2911,11 @@ static gboolean gst_encode_bin_block(GstEncodeBin *encodebin, gboolean value)
                                        g_object_set(encodebin->image_toggle, "block_data", TRUE, NULL);
                                        GST_INFO_OBJECT( encodebin, "image_toggle block_data TRUE" );
                                }
-                               break;   
+                               break;
                        default:
                                GST_WARNING_OBJECT (encodebin,"Invalid profile number = %d", encodebin->profile);
                                goto block_fail;
-                               break;    
+                               break;
                }
        } else { //release blocked-stream
                switch(encodebin->profile) {
@@ -2830,19 +2923,19 @@ static gboolean gst_encode_bin_block(GstEncodeBin *encodebin, gboolean value)
                                if(encodebin->audio_queue == NULL && encodebin->video_queue == NULL) {
                                        goto unblock_fail;
                                } else {
-                                       if(g_object_class_find_property(G_OBJECT_GET_CLASS(GST_OBJECT(encodebin->video_queue)), 
+                                       if(g_object_class_find_property(G_OBJECT_GET_CLASS(GST_OBJECT(encodebin->video_queue)),
                                                "empty-buffers") == NULL) {
                                                GST_ERROR_OBJECT(encodebin, "The queue element doesn't support 'empty-buffers' property");
                                                goto unblock_fail;
-                                       }                               
+                                       }
                                        if( encodebin->video_toggle )
                                        {
                                                g_object_set(encodebin->video_toggle, "block-data", FALSE , NULL);
                                                GST_INFO_OBJECT( encodebin, "video_toggle block-data FALSE" );
                                        }
-                                       
+
                                        if(encodebin->audio_queue != NULL)
-                                       {                                       
+                                       {
                                                g_object_set(encodebin->audio_queue, "empty-buffers", FALSE , NULL);
                                                GST_INFO_OBJECT( encodebin, "audio_queue empty-buffers FALSE" );
                                        }
@@ -2852,13 +2945,13 @@ static gboolean gst_encode_bin_block(GstEncodeBin *encodebin, gboolean value)
                                break;
                        case GST_ENCODE_BIN_PROFILE_AUDIO:
                                if(encodebin->audio_queue == NULL) {
-                                       goto unblock_fail;                                      
-                               } else {                
-                                       if(g_object_class_find_property(G_OBJECT_GET_CLASS(GST_OBJECT(encodebin->audio_queue)), 
+                                       goto unblock_fail;
+                               } else {
+                                       if(g_object_class_find_property(G_OBJECT_GET_CLASS(GST_OBJECT(encodebin->audio_queue)),
                                                "empty-buffers") == NULL) {
                                                GST_ERROR_OBJECT(encodebin, "The queue element doesn't support 'empty-buffers' property");
                                                goto unblock_fail;
-                                       }                               
+                                       }
                                        g_object_set(encodebin->audio_queue, "empty-buffers", FALSE , NULL);
                                        GST_INFO_OBJECT( encodebin, "audio_queue empty-buffers FALSE" );
                                }
@@ -2866,16 +2959,16 @@ static gboolean gst_encode_bin_block(GstEncodeBin *encodebin, gboolean value)
                        case GST_ENCODE_BIN_PROFILE_IMAGE:
                                if(encodebin->image_toggle == NULL) {
                                        goto unblock_fail;
-                               } else {                                
+                               } else {
                                        g_object_set(encodebin->image_toggle, "block_data", FALSE, NULL);
                                        GST_INFO_OBJECT( encodebin, "image_toggle block_data FALSE" );
                                }
-                               break;   
+                               break;
                        default:
                                GST_WARNING_OBJECT (encodebin,"Invalid profile number = %d", encodebin->profile);
                                goto unblock_fail;
-                               break;    
-               }       
+                               break;
+               }
        }
        encodebin->block = value;
        return TRUE;
@@ -2883,17 +2976,17 @@ static gboolean gst_encode_bin_block(GstEncodeBin *encodebin, gboolean value)
 block_fail:
        GST_ERROR_OBJECT(encodebin, "encodebin block failed");
        return FALSE;
-       
-unblock_fail:  
-       GST_ERROR_OBJECT(encodebin, "encodebin unblock failed");        
-       return FALSE;  
+
+unblock_fail:
+       GST_ERROR_OBJECT(encodebin, "encodebin unblock failed");
+       return FALSE;
 }
 
 static gboolean gst_encode_bin_pause(GstEncodeBin *encodebin, gboolean value)
 {
        GstClock *clock = NULL;
 
-       if(value) { 
+       if(value) {
                /* pause stream*/
                //Block src of encode bin
                if (!gst_encode_bin_block(encodebin, TRUE))
@@ -2913,7 +3006,7 @@ static gboolean gst_encode_bin_pause(GstEncodeBin *encodebin, gboolean value)
                                base_time = gst_element_get_base_time(GST_ELEMENT(encodebin));
 
                                encodebin->paused_time = current_time - base_time;
-                               
+
                                GST_INFO_OBJECT (encodebin, "Encodebin is in running-pause at [%"GST_TIME_FORMAT"]."
                                        , GST_TIME_ARGS(encodebin->paused_time));
                        }
@@ -2921,15 +3014,15 @@ static gboolean gst_encode_bin_pause(GstEncodeBin *encodebin, gboolean value)
                        {
                                encodebin->paused_time = 0;
                                encodebin->total_offset_time = 0;
-                               
+
                                GST_WARNING_OBJECT (encodebin, "There is no clock in Encodebin.");
                        }
                }
-#if 0 //def GST_ENCODE_BIN_SIGNAL_ENABLE               
+#if 0 //def GST_ENCODE_BIN_SIGNAL_ENABLE
                g_signal_emit (G_OBJECT (encodebin), gst_encode_bin_signals[SIGNAL_STREAM_PAUSE], 0, TRUE);
-#endif         
+#endif
        }
-       else { 
+       else {
                /* release paused-stream*/
                if (encodebin->paused_time != 0)
                {
@@ -2941,10 +3034,10 @@ static gboolean gst_encode_bin_pause(GstEncodeBin *encodebin, gboolean value)
                                current_time = gst_clock_get_time(clock);
                                base_time = gst_element_get_base_time(GST_ELEMENT(encodebin));
                                paused_gap = current_time - base_time - encodebin->paused_time;
-                               
+
                                encodebin->total_offset_time += paused_gap;
                                encodebin->paused_time = 0;
-                               
+
                                GST_INFO_OBJECT (encodebin, "Encodebin now resumes. Offset delay [%"GST_TIME_FORMAT"], Total offset delay [%"GST_TIME_FORMAT"]"
                                        , GST_TIME_ARGS(paused_gap) , GST_TIME_ARGS(encodebin->total_offset_time));
                        }
@@ -2952,7 +3045,7 @@ static gboolean gst_encode_bin_pause(GstEncodeBin *encodebin, gboolean value)
                        {
                                encodebin->paused_time = 0;
                                encodebin->total_offset_time = 0;
-                               
+
                                GST_WARNING_OBJECT (encodebin, "There is no clock in Encodebin.");
                        }
                }
@@ -2965,26 +3058,26 @@ static gboolean gst_encode_bin_pause(GstEncodeBin *encodebin, gboolean value)
                        GST_WARNING_OBJECT (encodebin, "Fail to Unblock Encodebin.");
                        goto resume_fail;
                }
-#if 0 //def GST_ENCODE_BIN_SIGNAL_ENABLE               
+#if 0 //def GST_ENCODE_BIN_SIGNAL_ENABLE
                g_signal_emit (G_OBJECT (encodebin), gst_encode_bin_signals[SIGNAL_STREAM_RESUME], 0, TRUE);
-#endif         
+#endif
        }
        encodebin->pause = value;
        return TRUE;
 
 pause_fail:
        GST_WARNING_OBJECT (encodebin, "Fail to pause Encodebin");
-#ifdef GST_ENCODE_BIN_SIGNAL_ENABLE            
+#ifdef GST_ENCODE_BIN_SIGNAL_ENABLE
                g_signal_emit (G_OBJECT (encodebin), gst_encode_bin_signals[SIGNAL_STREAM_PAUSE], 0, FALSE);
-#endif 
+#endif
        return FALSE;
 
-resume_fail:   
+resume_fail:
        GST_WARNING_OBJECT (encodebin, "Fail to resume Encodebin");
-#ifdef GST_ENCODE_BIN_SIGNAL_ENABLE            
+#ifdef GST_ENCODE_BIN_SIGNAL_ENABLE
                g_signal_emit (G_OBJECT (encodebin), gst_encode_bin_signals[SIGNAL_STREAM_RESUME], 0, FALSE);
-#endif         
-       return FALSE;   
+#endif
+       return FALSE;
 }
 
 static gboolean
@@ -3011,9 +3104,9 @@ gst_encode_bin_release_pipeline (GstElement *element,
     gst_element_unlink (encodebin->video_queue, encodebin->video_encode);
   }
 
-  gst_pad_unlink (gst_element_get_pad (encodebin->audio_encode, "src"), 
+  gst_pad_unlink (gst_element_get_pad (encodebin->audio_encode, "src"),
                        encodebin->mux_audio_sinkpad);
-  gst_pad_unlink (gst_element_get_pad (encodebin->video_encode, "src"), 
+  gst_pad_unlink (gst_element_get_pad (encodebin->video_encode, "src"),
                        encodebin->mux_video_sinkpad);
 
   gst_bin_remove_many (GST_BIN (element),
@@ -3042,7 +3135,7 @@ gst_encode_bin_audsink_set_caps (GstPad * pad, GstCaps * vscaps)
 //     const GValue *codec_data;
        gint channels, rate;
 
-       encodebin = GST_ENCODE_BIN (gst_pad_get_parent (pad));  
+       encodebin = GST_ENCODE_BIN (gst_pad_get_parent (pad));
 
        structure = gst_caps_get_structure (vscaps, 0);
 //     mimetype = gst_structure_get_name (structure);
@@ -3095,11 +3188,11 @@ gst_encode_bin_vidsink_set_caps (GstPad * pad, GstCaps * vscaps)
 
        encodebin->fps = gst_value_get_fraction_numerator(fps);
 
-       if(encodebin->high_speed_fps > 0)
+       if(encodebin->high_speed_fps > 0 && encodebin->fps > 0)
        {
                encodebin->multiple =(encodebin->high_speed_fps)/(encodebin->fps);
        }
-       
+
        {
                guint32 format;
 
@@ -3169,15 +3262,15 @@ static gboolean gst_encode_bin_imgsink_set_caps (GstPad * pad, GstCaps * vscaps)
                                break;
                }
        }
-       gst_object_unref (encodebin);   
+       gst_object_unref (encodebin);
        return TRUE;
-       
+
 refuse_caps:
        {
                GST_WARNING_OBJECT (encodebin, "refused caps %" GST_PTR_FORMAT, vscaps);
                gst_object_unref (encodebin);
                return FALSE;
-       }  
+       }
 
 }
 
@@ -3189,7 +3282,7 @@ gst_encode_bin_video_probe(GstPad *pad, GstBuffer *buffer, GstEncodeBin *encodeb
                GST_WARNING_OBJECT (encodebin, "encodebin is Null.");
                return TRUE;
        }
-       
+
        //Adjusting timestamp of video source
        GST_BUFFER_TIMESTAMP(buffer) -= encodebin->total_offset_time;
 
@@ -3204,7 +3297,7 @@ gst_encode_bin_video_probe_hs(GstPad *pad, GstBuffer *buffer, GstEncodeBin *enco
                GST_WARNING_OBJECT (encodebin, "encodebin is Null.");
                return TRUE;
        }
-       
+
        GST_BUFFER_TIMESTAMP(buffer)    *= encodebin->multiple;
        return TRUE;
 }
@@ -3217,7 +3310,7 @@ gst_encode_bin_audio_probe(GstPad *pad, GstBuffer *buffer, GstEncodeBin *encodeb
                GST_WARNING_OBJECT (encodebin, "encodebin is Null.");
                return TRUE;
        }
-       
+
        //Adjusting timestamp of video source
        GST_BUFFER_TIMESTAMP(buffer) -= encodebin->total_offset_time;
 
@@ -3274,5 +3367,5 @@ plugin_init (GstPlugin * plugin)
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
     "encodebin",
-    "EXT encoder bin", 
+    "EXT encoder bin",
     plugin_init, VERSION, "LGPL", "Samsung Electronics Co", "http://www.samsung.com/")
index 64c3a64..136fc92 100644 (file)
@@ -69,72 +69,72 @@ struct _GstEncodeBin
   GMutex *mutex;
 
   /* pads */
-  GstPad              *srcpad;
-  GstPad              *video_sinkpad;
-  GstPad              *audio_sinkpad;
-  GstPad              *image_sinkpad;
-  GstPad              *mux_audio_sinkpad;
-  GstPad              *mux_video_sinkpad;
+  GstPad *srcpad;
+  GstPad *video_sinkpad;
+  GstPad *audio_sinkpad;
+  GstPad *image_sinkpad;
+  GstPad *mux_audio_sinkpad;
+  GstPad *mux_video_sinkpad;
 
   /* sinkpads, video first */
-  GSList              *sinkpads;
+  GSList *sinkpads;
 
   /* video restricted to 1 pad */
-  guint               video_pads, audio_pads;
-
-  gint         profile;
-  gint         fps;
-  gint         high_speed_fps; 
-  gint         multiple;  
-  gchar                *venc_name;
-  gchar                *aenc_name;
-  gchar                *ienc_name;  
-  gchar                *mux_name;
-
-
-  GstCaps      *vcaps;
-  GstCaps      *acaps;
-  GstCaps      *icaps;
-  
-  gboolean     auto_audio_convert;
-  gboolean     auto_audio_resample;
-  gboolean     auto_color_space;
-  gboolean     block;
-  gboolean     pause;
-  gboolean     use_video_toggle;
-  gboolean     use_venc_queue;
-  gboolean     use_aenc_queue;  
-  
+  guint video_pads, audio_pads;
+
+  gint profile;
+  gint fps;
+  gint high_speed_fps;
+  gint multiple;
+  gchar *venc_name;
+  gchar *aenc_name;
+  gchar *ienc_name;
+  gchar *mux_name;
+  gchar *vconv_name;
+
+  GstCaps *vcaps;
+  GstCaps *acaps;
+  GstCaps *icaps;
+
+  gboolean auto_audio_convert;
+  gboolean auto_audio_resample;
+  gboolean auto_color_space;
+  gboolean block;
+  gboolean pause;
+  gboolean use_video_toggle;
+  gboolean use_venc_queue;
+  gboolean use_aenc_queue;
+
   GstElement *audio_queue;
-  GstElement *video_queue;  
-  GstElement *video_encode_queue;    
-  GstElement *audio_encode_queue;      
-  GstElement *image_queue;    
-  
+  GstElement *video_queue;
+  GstElement *video_encode_queue;
+  GstElement *audio_encode_queue;
+  GstElement *image_queue;
+
   GstElement *audio_encode;
   GstElement *video_encode;
-  GstElement *image_encode;  
+  GstElement *image_encode;
+
+  GstElement *vcapsfilter;
+  GstElement *acapsfilter;
+  GstElement *icapsfilter;
 
-  GstElement *vcapsfilter;  
-  GstElement *acapsfilter;    
-  GstElement *icapsfilter;      
-  
   GstElement *video_toggle;
-  GstElement *image_toggle;  
-  GstElement *color_space;  
-  GstElement *audio_conv;  
+  GstElement *image_toggle;
+  GstElement *color_space;
+  GstElement *audio_conv;
   GstElement *audio_sample;
-  
+
   GstElement *mux;
 
   /* pause/resume variables */
-  GstClockTime         paused_time;                    /* pipeline time when pausing */
-  GstClockTime         total_offset_time;              /* delayed time which is due to pause */
-  gulong               vsink_probeid;
-  gulong               vsink_hs_probeid;
-  gulong               asink_probeid;
-  gulong               veque_sig_id;
-  gulong               aeque_sig_id;  
+  GstClockTime paused_time;             /* pipeline time when pausing */
+  GstClockTime total_offset_time;       /* delayed time which is due to pause */
+  gulong vsink_probeid;
+  gulong vsink_hs_probeid;
+  gulong asink_probeid;
+  gulong veque_sig_id;
+  gulong aeque_sig_id;
 };
 
 struct _GstEncodeBinClass
index 8521916..8a88d14 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) $(MMTA_CFLAGS)
-libgstevasimagesink_la_LIBADD = $(GST_LIBS) $(GST_VIDEO_LIBS) $(EFL_LIBS) $(MMTA_LIBS)
+libgstevasimagesink_la_CFLAGS = $(GST_CFLAGS) $(GST_VIDEO_CFLAGS) $(EFL_CFLAGS) $(NATIVE_BUFFER_CFLAGS) $(TBM_CFLAGS)
+libgstevasimagesink_la_LIBADD = $(GST_LIBS) $(GST_VIDEO_LIBS) $(EFL_LIBS) $(NATIVE_BUFFER_LIBS) $(TBM_LIBS)
 libgstevasimagesink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstevasimagesink_la_LIBTOOLFLAGS = --tag=disable-static
 
old mode 100644 (file)
new mode 100755 (executable)
index f9f9d05..3e8504b
@@ -42,6 +42,7 @@
 
 #define CAP_WIDTH "width"
 #define CAP_HEIGHT "height"
+//#define DUMP_IMG
 
 GST_DEBUG_CATEGORY_STATIC (gst_evas_image_sink_debug);
 #define GST_CAT_DEFAULT gst_evas_image_sink_debug
@@ -58,10 +59,137 @@ enum
        PROP_0,
        PROP_EVAS_OBJECT,
        PROP_EVAS_OBJECT_SHOW,
+#ifdef USE_TBM_SURFACE
+       PROP_ROTATE_ANGLE,
+       PROP_DISPLAY_GEOMETRY_METHOD,
+       PROP_ENABLE_FLUSH_BUFFER,
+       PROP_FLIP
+#endif
+};
+
+enum
+{
+       UPDATE_FALSE,
+       UPDATE_TRUE
 };
 
 #define COLOR_DEPTH 4
 #define GL_X11_ENGINE "gl_x11"
+#define DO_RENDER_FROM_FIMC 1
+#define SIZE_FOR_UPDATE_VISIBILITY sizeof(gchar)
+
+#ifdef USE_TBM_SURFACE
+#define MAX_ECOREPIPE_BUFFER_CNT 4
+#define DEBUGLOG_DEFAULT_COUNT 8
+#define SIZE_FOR_NATIVE_INDEX sizeof(gint)
+
+/* max channel count *********************************************************/
+#define SCMN_IMGB_MAX_PLANE         (4)
+
+/* image buffer definition ***************************************************
+
+    +------------------------------------------+ ---
+    |                                          |  ^
+    |     a[], p[]                             |  |
+    |     +---------------------------+ ---    |  |
+    |     |                           |  ^     |  |
+    |     |<---------- w[] ---------->|  |     |  |
+    |     |                           |  |     |  |
+    |     |                           |        |
+    |     |                           |  h[]   |  e[]
+    |     |                           |        |
+    |     |                           |  |     |  |
+    |     |                           |  |     |  |
+    |     |                           |  v     |  |
+    |     +---------------------------+ ---    |  |
+    |                                          |  v
+    +------------------------------------------+ ---
+
+    |<----------------- s[] ------------------>|
+*/
+
+typedef struct
+{
+       /* width of each image plane */
+       int w[SCMN_IMGB_MAX_PLANE];
+       /* height of each image plane */
+       int h[SCMN_IMGB_MAX_PLANE];
+       /* stride of each image plane */
+       int s[SCMN_IMGB_MAX_PLANE];
+       /* elevation of each image plane */
+       int e[SCMN_IMGB_MAX_PLANE];
+       /* user space address of each image plane */
+       void *a[SCMN_IMGB_MAX_PLANE];
+       /* physical address of each image plane, if needs */
+       void *p[SCMN_IMGB_MAX_PLANE];
+       /* color space type of image */
+       int cs;
+       /* left postion, if needs */
+       int x;
+       /* top position, if needs */
+       int y;
+       /* to align memory */
+       int __dummy2;
+       /* arbitrary data */
+       int data[16];
+       /* dma buf fd */
+       int fd[SCMN_IMGB_MAX_PLANE];
+       /* buffer share method */
+       int buf_share_method;
+       /* Y plane size in case of ST12 */
+       int y_size;
+       /* UV plane size in case of ST12 */
+       int uv_size;
+       /* Tizen buffer object */
+       void *bo[SCMN_IMGB_MAX_PLANE];
+       /* JPEG data */
+       void *jpeg_data;
+       /* JPEG size */
+       int jpeg_size;
+       /* TZ memory buffer */
+       int tz_enable;
+} SCMN_IMGB;
+#endif
+
+#define EVASIMAGESINK_SET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object, x_usr_data ) \
+do \
+{ \
+       if (x_evas_image_object) { \
+               GST_LOG("object callback add"); \
+               evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event, x_usr_data); \
+               evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event, x_usr_data); \
+       } \
+}while(0)
+
+#define EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object ) \
+do \
+{ \
+       if (x_evas_image_object) { \
+               GST_LOG("object callback del"); \
+               evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event); \
+               evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event); \
+       } \
+}while(0)
+
+#ifdef USE_TBM_SURFACE
+#define EVASIMAGESINK_SET_EVAS_EVENT_CALLBACK( x_evas, x_usr_data ) \
+do \
+{ \
+       if (x_evas) { \
+               GST_DEBUG("callback add... evas_callback_render_pre.. evas : %p esink : %p", x_evas, x_usr_data); \
+               evas_event_callback_add (x_evas, EVAS_CALLBACK_RENDER_PRE, evas_callback_render_pre, x_usr_data); \
+       } \
+}while(0)
+
+#define EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK( x_evas ) \
+do \
+{ \
+       if (x_evas) { \
+               GST_DEBUG("callback del... evas_callback_render_pre"); \
+               evas_event_callback_del (x_evas, EVAS_CALLBACK_RENDER_PRE, evas_callback_render_pre); \
+       } \
+}while(0)
+#endif
 
 GMutex *instance_lock;
 guint instance_lock_count;
@@ -83,6 +211,14 @@ is_evas_image_object (Evas_Object *obj)
        return FALSE;
 }
 
+#ifdef USE_TBM_SURFACE
+gint
+gst_evas_image_sink_ref_count (GstBuffer * buf)
+{
+       return GST_OBJECT_REFCOUNT_VALUE(GST_BUFFER_CAST(buf));
+}
+#endif
+
 /* the capabilities of the inputs.
  *
  * BGRx format
@@ -90,8 +226,15 @@ is_evas_image_object (Evas_Object *obj)
 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
                GST_PAD_SINK,
                GST_PAD_ALWAYS,
+#ifdef USE_FIMCC
                GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx));
-
+#endif
+#ifdef USE_TBM_SURFACE
+               GST_STATIC_CAPS(GST_VIDEO_CAPS_YUV ("I420") ";"
+                                               GST_VIDEO_CAPS_YUV ("NV12") ";"
+                                               GST_VIDEO_CAPS_YUV ("SN12"))
+);
+#endif
 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);
@@ -100,8 +243,20 @@ static gboolean gst_evas_image_sink_set_caps (GstBaseSink *base_sink, GstCaps *c
 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 evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
+#ifdef USE_TBM_SURFACE
+static void evas_callback_render_pre (void *data, Evas *e, void *event_info);
+static GstFlowReturn gst_esink_epipe_reset(GstEvasImageSink *esink);
+static gboolean gst_esink_make_flush_buffer(GstEvasImageSink *esink);
+static void _release_flush_buffer(GstEvasImageSink *esink);
+static void gst_evas_image_sink_update_geometry (GstEvasImageSink *esink, GstVideoRectangle *result);
+static void gst_evas_image_sink_apply_geometry (GstEvasImageSink *esink);
+#endif
+#ifdef DUMP_IMG
+int util_write_rawdata (const char *file, const void *data, unsigned int size);
+int g_cnt = 0;
+#endif
 
 static void
 gst_evas_image_sink_base_init (gpointer gclass)
@@ -112,7 +267,7 @@ gst_evas_image_sink_base_init (gpointer gclass)
                "EvasImageSink",
                "VideoSink",
                "Video sink element for evas image object",
-               "Wonguk Jeong <wonguk.jeong@samsung.com>");
+               "Samsung Electronics <www.samsung.com>");
 
        gst_element_class_add_pad_template (element_class,
        gst_static_pad_template_get (&sink_factory));
@@ -138,7 +293,20 @@ gst_evas_image_sink_class_init (GstEvasImageSinkClass *klass)
                g_param_spec_pointer ("evas-object", "Destination Evas Object", "Destination evas image object", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
        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));
-
+#ifdef USE_TBM_SURFACE
+       g_object_class_install_property(gobject_class, PROP_ROTATE_ANGLE,
+               g_param_spec_int("rotate", "Rotate angle", "Rotate angle of display output", DEGREE_0, DEGREE_NUM, DEGREE_0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+       g_object_class_install_property(gobject_class, PROP_DISPLAY_GEOMETRY_METHOD,
+               g_param_spec_int("display-geometry-method", "Display geometry method",
+                       "Geometrical method for display", DISP_GEO_METHOD_LETTER_BOX, DISP_GEO_METHOD_NUM, DISP_GEO_METHOD_LETTER_BOX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+       g_object_class_install_property (gobject_class, PROP_ENABLE_FLUSH_BUFFER,
+               g_param_spec_boolean("enable-flush-buffer", "Enable flush buffer mechanism",
+                       "Enable flush buffer mechanism when state change(PAUSED_TO_READY)",
+                       TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+       g_object_class_install_property(gobject_class, PROP_FLIP,
+               g_param_spec_int("flip", "Display flip",
+                       "Flip for display", FLIP_NONE, FLIP_NUM, FLIP_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
        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);
@@ -148,16 +316,39 @@ gst_evas_image_sink_class_init (GstEvasImageSinkClass *klass)
 static void
 gst_evas_image_sink_fini (gpointer data, GObject *obj)
 {
-       GST_INFO ("enter");
+       GST_DEBUG ("[ENTER]");
 
        GstEvasImageSink *esink = GST_EVASIMAGESINK (obj);
        if (!esink) {
                return;
        }
+#ifdef USE_FIMCC
        if (esink->oldbuf) {
                gst_buffer_unref (esink->oldbuf);
        }
+#endif
 
+       if (esink->eo) {
+#ifdef USE_TBM_SURFACE
+               EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo));
+               GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo);
+#endif
+               EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo);
+               GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo);
+               evas_object_image_data_set(esink->eo, NULL);
+       }
+#ifdef USE_TBM_SURFACE
+       if (esink->display_buffer_lock) {
+               g_mutex_free (esink->display_buffer_lock);
+               esink->display_buffer_lock = NULL;
+       }
+       if (esink->flow_lock) {
+               g_mutex_free (esink->flow_lock);
+               esink->flow_lock = NULL;
+       }
+       esink->eo = NULL;
+       esink->epipe = NULL;
+#endif
        g_mutex_lock (instance_lock);
        instance_lock_count--;
        g_mutex_unlock (instance_lock);
@@ -165,29 +356,121 @@ gst_evas_image_sink_fini (gpointer data, GObject *obj)
                g_mutex_free (instance_lock);
                instance_lock = NULL;
        }
+
+       GST_DEBUG ("[LEAVE]");
+}
+
+#ifdef USE_TBM_SURFACE
+static void
+gst_evas_image_sink_reset (GstEvasImageSink *esink)
+{
+       int i = 0;
+       tbm_bo_handle bo_handle;
+
+       GST_DEBUG("gst_evas_image_sink_reset start");
+
+       g_mutex_lock(esink->display_buffer_lock);
+
+       for(i=0; i<NATIVE_BUFFER_NUM; i++)
+       {
+               if(esink->displaying_buffer[i].tbm_surf)
+               {
+                       tbm_surface_destroy(esink->displaying_buffer[i].tbm_surf);
+                       esink->displaying_buffer[i].tbm_surf = NULL;
+               }
+               if(esink->displaying_buffer[i].buffer)
+               {
+                       if(esink->displaying_buffer[i].ref_count)
+                       {
+                               if(esink->displaying_buffer[i].bo) {
+                                       bo_handle = tbm_bo_map(esink->displaying_buffer[i].bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
+                                       if (!bo_handle.ptr) {
+                                               GST_WARNING("failed to map bo [%p]", esink->displaying_buffer[i].bo);
+                                       }
+                                       else
+                                               tbm_bo_unmap(esink->displaying_buffer[i].bo);
+                               }
+                               else
+                                       GST_WARNING("there is no bo information. so skip to map bo");
+
+                               GST_WARNING("[reset] unreffing gst %p", esink->displaying_buffer[i].buffer);
+
+                               while(esink->displaying_buffer[i].ref_count)
+                               {
+                                       GST_WARNING("index[%d]'s buffer ref count=%d",i,gst_evas_image_sink_ref_count (esink->displaying_buffer[i].buffer));
+                                       esink->displaying_buffer[i].ref_count--;
+                                       gst_buffer_unref(esink->displaying_buffer[i].buffer);
+                               }
+                       }
+                       esink->displaying_buffer[i].buffer = NULL;
+               }
+               if(esink->displaying_buffer[i].bo)
+                       esink->displaying_buffer[i].bo = NULL;
+       }
+       esink->prev_buf = NULL;
+       esink->prev_index = -1;
+       esink->cur_index = -1;
+
+       esink->eo_size.x = esink->eo_size.y =
+       esink->eo_size.w = esink->eo_size.h = 0;
+       esink->use_ratio = FALSE;
+       esink->sent_buffer_cnt = 0;
+
+       g_mutex_unlock(esink->display_buffer_lock);
 }
+#endif
 
+#ifdef USE_FIMCC
 static void
 evas_image_sink_cb_pipe (void *data, void *buffer, unsigned int nbyte)
+#endif
+#ifdef USE_TBM_SURFACE
+static void
+evas_image_sink_cb_pipe (void *data, int *buffer_index, unsigned int nbyte)
+#endif
 {
-       GstBuffer *buf;
        GstEvasImageSink *esink = data;
+#ifdef USE_FIMCC
+       GstBuffer *buf;
        void *img_data;
-
-       if (!data || !buffer) {
+#endif
+       GST_DEBUG ("[ENTER]");
+       if (!esink || !esink->eo) {
+               GST_WARNING ("esink : %p, or eo is NULL returning", esink);
                return;
        }
-       if (nbyte != sizeof (GstBuffer *)) {
+       GST_LOG("esink : %p, esink->eo : %x", esink, esink->eo);
+       if (nbyte == SIZE_FOR_UPDATE_VISIBILITY) {
+               if(!esink->object_show) {
+                       evas_object_hide(esink->eo);
+                       GST_INFO ("object hide..");
+               } else {
+                       evas_object_show(esink->eo);
+                       GST_INFO ("object show..");
+               }
+               GST_DEBUG ("[LEAVE]");
                return;
        }
-       if (!esink->eo) {
+#ifdef USE_FIMCC
+       if (!buffer || nbyte != sizeof (GstBuffer *)) {
+               GST_WARNING ("buffer %p, nbyte : %d, sizeof(GstBuffer *) : %d", buffer, nbyte, sizeof (GstBuffer *));
                return;
        }
+#endif
+#ifdef USE_TBM_SURFACE
+       int index = 0;
+       index = *buffer_index;
+       if ((index<0 || index>=NATIVE_BUFFER_NUM) || nbyte != SIZE_FOR_NATIVE_INDEX)    {
+               GST_WARNING ("index : %d, nbyte : %d", index, nbyte);
+               return;
+       }
+#endif
        if (GST_STATE(esink) < GST_STATE_PAUSED) {
                GST_WARNING ("WRONG-STATE(%d) for rendering, skip this frame", GST_STATE(esink));
                return;
        }
 
+#ifdef USE_FIMCC
        memcpy (&buf, buffer, sizeof (GstBuffer *));
        if (!buf) {
                GST_ERROR ("There is no buffer");
@@ -195,16 +478,142 @@ evas_image_sink_cb_pipe (void *data, void *buffer, unsigned int nbyte)
        }
        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));
+       } else if (esink->present_data_addr != DO_RENDER_FROM_FIMC) {
+               GST_WARNING ("skip rendering this buffer, present_data_addr:%d, DO_RENDER_FROM_FIMC:%d", esink->present_data_addr, DO_RENDER_FROM_FIMC);
                return;
        }
+#endif
+#ifdef USE_TBM_SURFACE
+       g_mutex_lock(esink->display_buffer_lock);
+       if(esink->tbm_surface_format == TBM_FORMAT_NV12) {
+               if (!esink->displaying_buffer[index].tbm_surf) {
+                       GST_ERROR("the index's nbuffer was already NULL, so return");
+                       g_mutex_unlock(esink->display_buffer_lock);
+                       return;
+               }
+               GST_LOG("received (bo %p, gst %p) index num : %d", esink->displaying_buffer[index].bo, esink->displaying_buffer[index].buffer, index);
+       } else if(esink->tbm_surface_format == TBM_FORMAT_YUV420) {
+               GST_LOG("received (bo %p) index num : %d", esink->displaying_buffer[index].bo, index);
+       }
 
-       MMTA_ACUM_ITEM_BEGIN("eavsimagesink _cb_pipe total", FALSE);
+       Evas_Native_Surface surf;
+       surf.type = EVAS_NATIVE_SURFACE_TBM;
+       surf.version = EVAS_NATIVE_SURFACE_VERSION;
+       surf.data.tizen.buffer = esink->displaying_buffer[index].tbm_surf;
+       surf.data.tizen.rot = esink->rotate_angle;
+       surf.data.tizen.flip = esink->flip;
 
+       GST_LOG("received (bo %p, gst %p) index num : %d", esink->displaying_buffer[index].bo, esink->displaying_buffer[index].buffer, index);
+
+       GstVideoRectangle result = {0};
+
+       evas_object_geometry_get(esink->eo, &esink->eo_size.x, &esink->eo_size.y, &esink->eo_size.w, &esink->eo_size.h);
+       if (!esink->eo_size.w || !esink->eo_size.h) {
+               GST_ERROR ("there is no information for evas object size");
+               g_mutex_unlock(esink->display_buffer_lock);
+               return;
+       }
+       gst_evas_image_sink_update_geometry(esink, &result);
+       if(!result.w || !result.h)
+       {
+               GST_ERROR("no information about geometry (%d, %d)", result.w, result.h);
+               g_mutex_unlock(esink->display_buffer_lock);
+               return;
+       }
+
+       if(esink->use_ratio)
+       {
+               surf.data.tizen.ratio = (float) esink->w / esink->h;
+               GST_LOG("set ratio for letter mode");
+       }
+       evas_object_size_hint_align_set(esink->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
+       evas_object_size_hint_weight_set(esink->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       if ( !esink->is_evas_object_size_set && esink->w > 0 && esink->h > 0) {
+               evas_object_image_size_set(esink->eo, esink->w, esink->h);
+               esink->is_evas_object_size_set = TRUE;
+       }
+#ifdef DUMP_IMG
+       int ret = 0;
+       char file_name[128];
+       char *dump_data;
+       guint size = esink->w*esink->h + (esink->w/2*esink->h/2)*2; //this size is for I420 format
+       tbm_bo_handle vaddr_dump;
+       if(g_cnt<20)
+       {
+               GST_WARNING ("DUMP IMG_%2.2d : buffer size(%d)", g_cnt, size);
+               sprintf(file_name, "DUMP_IMG_%2.2d.dump", g_cnt++);
+
+               dump_data = g_malloc(size);
+               vaddr_dump = tbm_bo_map(esink->displaying_buffer[index].bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
+               if (vaddr_dump.ptr) {
+                       tbm_bo_unmap(esink->displaying_buffer[index].bo);
+               }
+               memcpy (dump_data, vaddr_dump.ptr, size);
+
+               ret = util_write_rawdata(file_name, dump_data, size);
+               if (ret) {
+               GST_ERROR_OBJECT (esink, "util_write_rawdata() failed");
+               }
+               g_free(dump_data);
+       }
+#endif
+    evas_object_image_native_surface_set(esink->eo, &surf);
+       GST_DEBUG("native surface set finish");
+
+       if(result.x || result.y)
+               GST_LOG("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
+       evas_object_image_fill_set(esink->eo, result.x, result.y, result.w, result.h);
+
+       evas_object_image_pixels_dirty_set(esink->eo, EINA_TRUE);
+       GST_DEBUG_OBJECT (esink, "GEO_METHOD : src(%dx%d), dst(%dx%d), dst_x(%d), dst_y(%d), rotate(%d), flip(%d)",
+               esink->w, esink->h, esink->eo_size.w, esink->eo_size.h, esink->eo_size.x, esink->eo_size.y, esink->rotate_angle, esink->flip);
+
+       /* unref previous buffer */
+       if(esink->tbm_surface_format == TBM_FORMAT_NV12) {
+               if(esink->prev_buf && esink->displaying_buffer[esink->prev_index].ref_count)
+               {
+                       GST_DEBUG("before index %d's ref_count =%d, gst_buf %p",esink->prev_index,esink->displaying_buffer[esink->prev_index].ref_count, esink->prev_buf);
+                       esink->displaying_buffer[esink->prev_index].ref_count--;
+                       GST_DEBUG("after index %d's ref_count =%d, gst_buf %p",esink->prev_index,esink->displaying_buffer[esink->prev_index].ref_count, esink->prev_buf);
+                       /* Print debug log for 8 frame */
+                       if(esink->debuglog_cnt_ecoreCbPipe > 0)
+                       {
+                               GST_WARNING("(%d) ecore_cb_pipe unref index[%d] .. gst_buf %p", DEBUGLOG_DEFAULT_COUNT-(esink->debuglog_cnt_ecoreCbPipe), esink->prev_index, esink->prev_buf);
+                               esink->debuglog_cnt_ecoreCbPipe--;
+                       }
+                       if (esink->sent_buffer_cnt == MAX_ECOREPIPE_BUFFER_CNT)
+                               GST_WARNING("sent buffer cnt 4->3 so skip will be stop");
+
+                       esink->sent_buffer_cnt--;
+                       GST_DEBUG("prev gst_buffer %p's unref Start!!", esink->prev_buf);
+                       gst_buffer_unref(esink->prev_buf);
+                       GST_DEBUG("prev gst_buffer %p's unref End!!", esink->prev_buf);
+               } else {
+                       GST_DEBUG("ref_count=%d  unref prev gst_buffer %p", esink->displaying_buffer[esink->prev_index].ref_count,esink->prev_buf);
+               }
+
+               GST_DEBUG("Current gst_buf %p and index=%d is overwrited to Prev gst_buf %p & index %d",
+                       esink->displaying_buffer[index].buffer, index, esink->prev_buf, esink->prev_index );
+               esink->prev_buf = esink->displaying_buffer[index].buffer;
+               esink->prev_index = index;
+       }else if(esink->tbm_surface_format == TBM_FORMAT_YUV420) {
+               /* Print debug log for 8 frame */
+               if(esink->debuglog_cnt_ecoreCbPipe > 0)
+               {
+                       GST_WARNING("(%d) ecore_cb_pipe set native surface [%d]  tbm_surf[%p]",
+                               DEBUGLOG_DEFAULT_COUNT-(esink->debuglog_cnt_ecoreCbPipe), index, esink->displaying_buffer[index].tbm_surf);
+                       esink->debuglog_cnt_ecoreCbPipe--;
+               }
+               if (esink->sent_buffer_cnt == MAX_ECOREPIPE_BUFFER_CNT)
+                       GST_WARNING("sent buffer cnt 4->3 so skip will be stop");
+
+               esink->sent_buffer_cnt--;
+       }
+#endif
+#ifdef USE_FIMCC
        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);
+                       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) {
@@ -213,14 +622,14 @@ evas_image_sink_cb_pipe (void *data, void *buffer, unsigned int nbyte)
                        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);
-                       __ta__("evasimagesink memcpy in _cb_pipe", memcpy (img_data, GST_BUFFER_DATA (buf), esink->w * esink->h * COLOR_DEPTH););
+                       GST_DEBUG ("img_data(%x), GST_BUFFER_DATA(buf):%x, esink->w(%d),esink->h(%d), esink->eo(%x)",img_data,GST_BUFFER_DATA(buf),esink->w,esink->h,esink->eo);
+                       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));
+               GST_DEBUG ("GST_BUFFER_DATA(buf):%x, esink->eo(%x)",GST_BUFFER_DATA(buf),esink->eo);
                evas_object_image_data_set (esink->eo, GST_BUFFER_DATA (buf));
                evas_object_image_pixels_dirty_set (esink->eo, 1);
                if (esink->oldbuf) {
@@ -228,22 +637,170 @@ evas_image_sink_cb_pipe (void *data, void *buffer, unsigned int nbyte)
                }
                esink->oldbuf = buf;
        }
+#endif
+#ifdef USE_TBM_SURFACE
+       g_mutex_unlock(esink->display_buffer_lock);
+#endif
+       GST_DEBUG ("[LEAVE]");
+}
+#ifdef USE_TBM_SURFACE
+static void
+gst_evas_image_sink_update_geometry (GstEvasImageSink *esink, GstVideoRectangle *result)
+{
+       if (!esink || !esink->eo) {
+               GST_WARNING("there is no esink");
+               return;
+       }
 
-       MMTA_ACUM_ITEM_END("eavsimagesink _cb_pipe total", FALSE);
+       result->x = 0;
+       result->y = 0;
+
+       switch (esink->display_geometry_method)
+       {
+               case DISP_GEO_METHOD_LETTER_BOX:        // 0
+                       /* set black padding for letter box mode */
+                       GST_DEBUG("letter box mode");
+                       esink->use_ratio = TRUE;
+                       result->w = esink->eo_size.w;
+                       result->h = esink->eo_size.h;
+                       break;
+               case DISP_GEO_METHOD_ORIGIN_SIZE:       // 1
+                       GST_DEBUG("origin size mode");
+                       esink->use_ratio = FALSE;
+                       /* set coordinate for each case */
+                       result->x = (esink->eo_size.w-esink->w) / 2;
+                       result->y = (esink->eo_size.h-esink->h) / 2;
+                       result->w = esink->w;
+                       result->h = esink->h;
+                       break;
+               case DISP_GEO_METHOD_FULL_SCREEN:       // 2
+                       GST_DEBUG("full screen mode");
+                       esink->use_ratio = FALSE;
+                       result->w = esink->eo_size.w;
+                       result->h = esink->eo_size.h;
+                       break;
+               case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:       // 3
+                       GST_DEBUG("cropped full screen mode");
+                       esink->use_ratio = FALSE;
+                       /* compare evas object's ratio with video's */
+                       if((esink->eo_size.w/esink->eo_size.h) > (esink->w/esink->h))
+                       {
+                               result->w = esink->eo_size.w;
+                               result->h = esink->eo_size.w * esink->h / esink->w;
+                               result->y = -(result->h-esink->eo_size.h) / 2;
+                       }
+                       else
+                       {
+                               result->w = esink->eo_size.h * esink->w / esink->h;
+                               result->h = esink->eo_size.h;
+                               result->x = -(result->w-esink->eo_size.w) / 2;
+                       }
+                       break;
+               case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX: // 4
+                       GST_DEBUG("origin size or letter box mode");
+                       /* if video size is smaller than evas object's, it will be set to origin size mode */
+                       if((esink->eo_size.w > esink->w) && (esink->eo_size.h > esink->h))
+                       {
+                               GST_DEBUG("origin size mode");
+                               esink->use_ratio = FALSE;
+                               /* set coordinate for each case */
+                               result->x = (esink->eo_size.w-esink->w) / 2;
+                               result->y = (esink->eo_size.h-esink->h) / 2;
+                               result->w = esink->w;
+                               result->h = esink->h;
+                       }
+                       else
+                       {
+                               GST_DEBUG("letter box mode");
+                               esink->use_ratio = TRUE;
+                               result->w = esink->eo_size.w;
+                               result->h = esink->eo_size.h;
+                       }
+                       break;
+               default:
+                       GST_WARNING("unsupported mode.");
+                       break;
+       }
+       GST_DEBUG("geometry result [%d, %d, %d, %d]", result->x, result->y, result->w, result->h);
 }
+static void
+gst_evas_image_sink_apply_geometry (GstEvasImageSink *esink)
+{
+       if (!esink || !esink->eo) {
+               GST_WARNING("there is no esink");
+               return;
+       }
+
+       Evas_Native_Surface *surf = evas_object_image_native_surface_get(esink->eo);
+       GstVideoRectangle result = {0};
+
+       if(surf)
+       {
+               GST_DEBUG("native surface exists");
+               surf->data.tizen.rot = esink->rotate_angle;
+               surf->data.tizen.flip = esink->flip;
+               evas_object_image_native_surface_set(esink->eo, surf);
+
+               gst_evas_image_sink_update_geometry(esink, &result);
+
+               if(esink->use_ratio)
+               {
+                       surf->data.tizen.ratio = (float) esink->w / esink->h;
+                       GST_LOG("set ratio for letter mode");
+               }
+
+               if(result.x || result.y)
+                       GST_LOG("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
+
+               evas_object_image_fill_set(esink->eo, result.x, result.y, result.w, result.h);
+       }
+       else
+               GST_WARNING("there is no surf");
+}
+#endif
 
 static void
 gst_evas_image_sink_init (GstEvasImageSink *esink, GstEvasImageSinkClass *gclass)
 {
-       GST_INFO ("enter");
+       GST_DEBUG ("[ENTER]");
 
        esink->eo = NULL;
        esink->epipe = NULL;
        esink->object_show = FALSE;
-       esink->gl_zerocopy = FALSE;
+       esink->update_visibility = UPDATE_FALSE;
        esink->is_evas_object_size_set = FALSE;
+#ifdef USE_FIMCC
+       esink->gl_zerocopy = FALSE;
        esink->present_data_addr = -1;
-
+#endif
+#ifdef USE_TBM_SURFACE
+       esink->display_buffer_lock = g_mutex_new ();
+       esink->flow_lock = g_mutex_new ();
+       int i = 0;
+       for (i=0; i<NATIVE_BUFFER_NUM; i++)
+       {
+               esink->displaying_buffer[i].tbm_surf = NULL;
+               esink->displaying_buffer[i].buffer = NULL;
+               esink->displaying_buffer[i].bo = NULL;
+               esink->displaying_buffer[i].ref_count = 0;
+       }
+       esink->prev_buf = NULL;
+       esink->prev_index = -1;
+       esink->cur_index = -1;
+       esink->enable_flush_buffer = TRUE;
+       esink->need_flush = FALSE;
+       esink->display_geometry_method = DISP_GEO_METHOD_LETTER_BOX;
+       esink->flip = FLIP_NONE;
+       esink->eo_size.x = esink->eo_size.y =
+       esink->eo_size.w = esink->eo_size.h = 0;
+       esink->use_ratio = FALSE;
+       esink->sent_buffer_cnt = 0;
+       esink->debuglog_cnt_showFrame = DEBUGLOG_DEFAULT_COUNT;
+       esink->debuglog_cnt_ecoreCbPipe = DEBUGLOG_DEFAULT_COUNT;
+
+       esink->src_buf_idx = 0;
+       esink->is_buffer_allocated = FALSE;
+#endif
        if(!instance_lock) {
                instance_lock = g_mutex_new();
        }
@@ -252,42 +809,229 @@ gst_evas_image_sink_init (GstEvasImageSink *esink, GstEvasImageSinkClass *gclass
        g_mutex_unlock (instance_lock);
 
        g_object_weak_ref (G_OBJECT (esink), gst_evas_image_sink_fini, NULL);
+
+       GST_DEBUG ("[LEAVE]");
 }
 
 static void
-evas_image_sink_cb_del_eo (void *data, Evas *e, Evas_Object *obj, void *event_info)
+evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
 {
+       GST_DEBUG ("[ENTER]");
+
        GstEvasImageSink *esink = data;
        if (!esink) {
                return;
        }
-
-       evas_object_event_callback_del (esink->eo, EVAS_CALLBACK_RESIZE, evas_image_sink_cb_resize_event);
+#ifdef USE_FIMCC
        if (esink->oldbuf) {
                gst_buffer_unref (esink->oldbuf);
                esink->oldbuf = NULL;
+       }
+#endif
+       if (esink->eo) {
+#ifdef USE_TBM_SURFACE
+               EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo));
+               GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo);
+#endif
+               EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo);
+               GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo);
+
+               evas_object_image_data_set(esink->eo, NULL);
                esink->eo = NULL;
        }
+       GST_DEBUG ("[LEAVE]");
 }
 
 static void
-evas_image_sink_cb_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
+evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
 {
-       int w = 0;
-       int h = 0;
+       int x, y, w, h;
+       x = y = w = h = 0;
+
+       GST_DEBUG ("[ENTER]");
+
        GstEvasImageSink *esink = data;
-       if (!esink) {
+       if (!esink || !esink->eo) {
                return;
        }
 
-       evas_object_geometry_get(esink->eo, NULL, NULL, &w, &h);
+       evas_object_geometry_get(esink->eo, &x, &y, &w, &h);
        if (!w || !h) {
-               GST_WARNING ("evas object size (w:%d,h:%d) was not set",w,h);
+               GST_WARNING ("evas object size (w:%d,h:%d) was not set", w, h);
        } else {
+#ifdef USE_TBM_SURFACE
+               esink->eo_size.x = x;
+               esink->eo_size.y = y;
+               esink->eo_size.w = w;
+               esink->eo_size.h = h;
+               GST_WARNING ("resize (x:%d, y:%d, w:%d, h:%d)", x, y, w, h);
+               gst_evas_image_sink_apply_geometry(esink);
+#endif
+#ifdef USE_FIMCC
                evas_object_image_fill_set(esink->eo, 0, 0, w, h);
-               GST_DEBUG ("evas object fill set (w:%d,h:%d)",w,h);
+               GST_DEBUG ("evas object fill set (w:%d,h:%d)", w, h);
+#endif
        }
+       GST_DEBUG ("[LEAVE]");
 }
+#ifdef USE_TBM_SURFACE
+static void
+evas_callback_render_pre (void *data, Evas *e, void *event_info)
+{
+       GstEvasImageSink *esink = data;
+       if (!esink || !esink->eo) {
+               GST_WARNING("there is no esink info.... esink : %p, or eo is NULL returning", esink);
+               return;
+       }
+       if(esink->need_flush && esink->flush_buffer)
+       {
+               g_mutex_lock(esink->display_buffer_lock);
+               Evas_Native_Surface surf;
+               GstVideoRectangle result = {0};
+
+               evas_object_geometry_get(esink->eo, &esink->eo_size.x, &esink->eo_size.y, &esink->eo_size.w, &esink->eo_size.h);
+               if (!esink->eo_size.w || !esink->eo_size.h) {
+                       GST_ERROR ("there is no information for evas object size");
+                       return;
+               }
+               gst_evas_image_sink_update_geometry(esink, &result);
+               if(!result.w || !result.h)
+               {
+                       GST_ERROR("no information about geometry (%d, %d)", result.w, result.h);
+                       return;
+               }
+
+               if(esink->use_ratio)
+               {
+                       surf.data.tizen.ratio = (float) esink->w / esink->h;
+                       GST_LOG("set ratio for letter mode");
+               }
+               evas_object_size_hint_align_set(esink->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
+               evas_object_size_hint_weight_set(esink->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+               if ( !esink->is_evas_object_size_set && esink->w > 0 && esink->h > 0) {
+                       evas_object_image_size_set(esink->eo, esink->w, esink->h);
+                       esink->is_evas_object_size_set = TRUE;
+               }
+
+               if(result.x || result.y)
+                       GST_LOG("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
+
+               evas_object_image_fill_set(esink->eo, result.x, result.y, result.w, result.h);
+
+               surf.type = EVAS_NATIVE_SURFACE_TBM;
+               surf.version = EVAS_NATIVE_SURFACE_VERSION;
+               surf.data.tizen.buffer = esink->flush_buffer->tbm_surf;
+               surf.data.tizen.rot = esink->rotate_angle;
+               surf.data.tizen.flip = esink->flip;
+               GST_DEBUG("use esink->flush buffer->tbm_surf (%p), rotate(%d), flip(%d)",
+                       esink->flush_buffer->tbm_surf, esink->rotate_angle, esink->flip);
+               evas_object_image_native_surface_set(esink->eo, &surf);
+               g_mutex_unlock(esink->display_buffer_lock);
+               esink->need_flush = FALSE;
+       }
+       evas_object_image_pixels_dirty_set (esink->eo, EINA_TRUE);
+       GST_LOG("dirty set finish");
+}
+
+static gboolean
+gst_evas_image_sink_release_source_buffer(GstEvasImageSink *esink)
+{
+       int i = 0;
+       tbm_bo_handle bo_handle;
+       g_mutex_lock(esink->display_buffer_lock);
+
+       for(i = 0; i < NATIVE_BUFFER_NUM; i++) {
+               GST_WARNING("[reset] reset gst %p", esink->displaying_buffer[i].buffer);
+               esink->displaying_buffer[i].bo = NULL;
+               esink->displaying_buffer[i].tbm_surf = NULL;
+               esink->displaying_buffer[i].ref_count = 0;
+       }
+
+       for(i = 0; i < SOURCE_BUFFER_NUM; i++) {
+               if(esink->src_buffer_info[i].bo) {
+                       tbm_bo_unmap(esink->src_buffer_info[i].bo);
+                       esink->src_buffer_info[i].bo = NULL;
+               }
+
+               if (esink->src_buffer_info[i].tbm_surf) {
+                       tbm_surface_destroy(esink->src_buffer_info[i].tbm_surf);
+                       esink->src_buffer_info[i].tbm_surf = NULL;
+               }
+       }
+
+       esink->is_buffer_allocated = FALSE;
+       esink->src_buf_idx = 0;
+       esink->prev_buf = NULL;
+       esink->prev_index = -1;
+       esink->cur_index = -1;
+
+       esink->eo_size.x = esink->eo_size.y =
+       esink->eo_size.w = esink->eo_size.h = 0;
+       esink->use_ratio = FALSE;
+       esink->sent_buffer_cnt = 0;
+
+       g_mutex_unlock(esink->display_buffer_lock);
+
+       return TRUE;
+}
+
+static gboolean
+gst_evas_image_sink_allocate_source_buffer(GstEvasImageSink *esink)
+{
+       int size = 0;
+       int idx = 0;
+       tbm_bo bo;
+       tbm_bo_handle vaddr;
+       GstFlowReturn ret=GST_FLOW_OK;
+
+       if (esink == NULL) {
+               GST_ERROR("handle is NULL");
+               return FALSE;
+       }
+
+       for(idx=0; idx < SOURCE_BUFFER_NUM; idx++) {
+               if(!esink->src_buffer_info[idx].tbm_surf) {
+                       /* create tbm surface */
+                       esink->src_buffer_info[idx].tbm_surf = tbm_surface_create(esink->w, esink->h, esink->tbm_surface_format);
+               }
+               if(!esink->src_buffer_info[idx].tbm_surf)
+               {
+                       GST_ERROR("tbm_surf is NULL!!");
+                       goto ALLOC_FAILED;
+               }
+
+               /* get bo and size */
+               bo = tbm_surface_internal_get_bo(esink->src_buffer_info[idx].tbm_surf, 0);
+               size = tbm_bo_size(bo);
+               if(!bo || !size)
+               {
+                       GST_ERROR("bo(%p), size(%d)", bo, size);
+                       goto ALLOC_FAILED;
+               }
+               esink->src_buffer_info[idx].bo = bo;
+
+               vaddr = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
+               if (!vaddr.ptr) {
+                       GST_WARNING_OBJECT(esink, "get vaddr failed pointer = %p", vaddr.ptr);
+                       tbm_bo_unmap(bo);
+                       goto ALLOC_FAILED;
+               } else {
+                       memset (vaddr.ptr, 0x0, size);
+                       GST_LOG_OBJECT (esink, "tbm_bo_map(VADDR) finished, bo(%p), vaddr(%p)", bo, vaddr.ptr);
+               }
+
+               esink->src_buffer_info[idx].usr_addr = vaddr.ptr;
+
+               GST_WARNING_OBJECT(esink, "src buffer index:%d , tbm surface : %p", idx, esink->src_buffer_info[idx].tbm_surf);
+       }
+
+       return TRUE;
+
+ALLOC_FAILED:
+       gst_evas_image_sink_release_source_buffer(esink);
+       return FALSE;
+}
+#endif
 
 static int
 evas_image_sink_get_size_from_caps (GstCaps *caps, int *w, int *h)
@@ -306,19 +1050,23 @@ evas_image_sink_get_size_from_caps (GstCaps *caps, int *w, int *h)
 
        r = gst_structure_get_int (s, CAP_WIDTH, &width);
        if (r == FALSE) {
+               GST_DEBUG("fail to get width from caps");
                return -1;
        }
 
        r = gst_structure_get_int (s, CAP_HEIGHT, &height);
        if (r == FALSE) {
+               GST_DEBUG("fail to get height from caps");
                return -1;
        }
 
        *w = width;
        *h = height;
+       GST_DEBUG ("size w(%d), h(%d)", width, height);
+
        return 0;
 }
-
+#ifdef USE_FIMCC
 static gboolean
 is_zerocopy_supported (Evas *e)
 {
@@ -378,14 +1126,15 @@ evas_image_sink_event_parse_data (GstEvasImageSink *esink, GstEvent *event)
 
        return 0;
 }
-
+#endif
 static gboolean
 gst_evas_image_sink_event (GstBaseSink *sink, GstEvent *event)
 {
+#ifdef USE_FIMCC
        GstEvasImageSink *esink = GST_EVASIMAGESINK (sink);
        GstMessage *msg;
        gchar *str;
-
+#endif
        switch (GST_EVENT_TYPE (event)) {
                case GST_EVENT_FLUSH_START:
                        GST_DEBUG ("GST_EVENT_FLUSH_START");
@@ -396,6 +1145,7 @@ gst_evas_image_sink_event (GstBaseSink *sink, GstEvent *event)
                case GST_EVENT_EOS:
                        GST_DEBUG ("GST_EVENT_EOS");
                        break;
+#ifdef USE_FIMCC
                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);
@@ -403,6 +1153,7 @@ gst_evas_image_sink_event (GstBaseSink *sink, GstEvent *event)
                                GST_ERROR ("evas_image_sink_event_parse_data() failed");
                        }
                        break;
+#endif
                default:
                        break;
        }
@@ -418,21 +1169,37 @@ gst_evas_image_sink_change_state (GstElement *element, GstStateChange transition
 {
        GstStateChangeReturn ret_state = GST_STATE_CHANGE_SUCCESS;
        GstEvasImageSink *esink = NULL;
+       GstFlowReturn ret=GST_FLOW_OK;
        esink = GST_EVASIMAGESINK(element);
-       int ret = 0;
 
        if(!esink) {
                GST_ERROR("can not get evasimagesink from element");
+               return GST_STATE_CHANGE_FAILURE;
        }
+
        switch (transition) {
                case GST_STATE_CHANGE_NULL_TO_READY:
-                       GST_INFO ("*** STATE_CHANGE_NULL_TO_READY ***");
+                       GST_WARNING ("*** STATE_CHANGE_NULL_TO_READY ***");
+#ifdef USE_TBM_SURFACE
+                       g_mutex_lock (esink->flow_lock);
+                       if (!is_evas_image_object (esink->eo)) {
+                               GST_ERROR_OBJECT (esink, "There is no evas image object..");
+                               g_mutex_unlock (esink->flow_lock);
+                               return GST_STATE_CHANGE_FAILURE;
+                       }
+                       g_mutex_unlock (esink->flow_lock);
+#endif
                        break;
                case GST_STATE_CHANGE_READY_TO_PAUSED:
-                       GST_INFO ("*** STATE_CHANGE_READY_TO_PAUSED ***");
+                       GST_WARNING ("*** STATE_CHANGE_READY_TO_PAUSED ***");
                        break;
                case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-                       GST_INFO ("*** STATE_CHANGE_PAUSED_TO_PLAYING ***");
+#ifdef USE_TBM_SURFACE
+                       /* Print debug log for 8 frame */
+                       esink->debuglog_cnt_showFrame = DEBUGLOG_DEFAULT_COUNT;
+                       esink->debuglog_cnt_ecoreCbPipe = DEBUGLOG_DEFAULT_COUNT;
+#endif
+                       GST_WARNING ("*** STATE_CHANGE_PAUSED_TO_PLAYING ***");
                        break;
                default:
                        break;
@@ -442,16 +1209,49 @@ gst_evas_image_sink_change_state (GstElement *element, GstStateChange transition
 
        switch (transition) {
                case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-                       GST_INFO ("*** STATE_CHANGE_PLAYING_TO_PAUSED ***");
+                       GST_WARNING ("*** STATE_CHANGE_PLAYING_TO_PAUSED ***");
                        break;
                case GST_STATE_CHANGE_PAUSED_TO_READY:
-                       GST_INFO ("*** STATE_CHANGE_PAUSED_TO_READY ***");
+                       GST_WARNING ("*** STATE_CHANGE_PAUSED_TO_READY ***");
+#ifdef USE_TBM_SURFACE
+                       Eina_Bool r;
+                       /* flush buffer, we will copy last buffer to keep image data and reset buffer list */
+                       GST_WARNING("esink->enable_flush_buffer : %d", esink->enable_flush_buffer);
+                       if(esink->enable_flush_buffer && esink->tbm_surface_format == TBM_FORMAT_NV12)
+                       {
+                                if (gst_esink_make_flush_buffer(esink) == FALSE) {
+                                       ret = gst_esink_epipe_reset(esink);
+                                       if(ret) {
+                                               GST_ERROR_OBJECT(esink, "evas epipe reset ret=%d, need to check",ret);
+                                               return GST_STATE_CHANGE_FAILURE;
+                                       }
+                                       gst_evas_image_sink_reset(esink);
+                               }
+                       }
+                       else {
+                               ret = gst_esink_epipe_reset(esink);
+                               if(ret) {
+                                       GST_ERROR_OBJECT(esink, "evas epipe reset ret=%d, need to check",ret);
+                                       return GST_STATE_CHANGE_FAILURE;
+                               }
+                               if(esink->tbm_surface_format == TBM_FORMAT_NV12) {
+                                       gst_evas_image_sink_reset(esink);
+                               } else if(esink->tbm_surface_format == TBM_FORMAT_YUV420) {
+                                       gst_evas_image_sink_release_source_buffer(esink);
+                               }
+                       }
+#endif
                        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);
+                       GST_WARNING ("*** STATE_CHANGE_READY_TO_NULL ***");
+#ifdef USE_TBM_SURFACE
+                       if(esink->flush_buffer)
+                               _release_flush_buffer(esink);
+                       EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo));
+#endif
+                       EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo);
                        if (esink->epipe) {
+                               GST_DEBUG("ecore-pipe will delete");
                                ecore_pipe_del (esink->epipe);
                                esink->epipe = NULL;
                        }
@@ -476,24 +1276,39 @@ gst_evas_image_sink_set_property (GObject *object, guint prop_id, const GValue *
                eo = g_value_get_pointer (value);
                if (is_evas_image_object (eo)) {
                        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);
-
+                               Eina_Bool r;
+#ifdef USE_TBM_SURFACE
+                               EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo));
+#endif
+                               /* delete evas object callbacks registrated on a previous evas image object */
+                               EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo);
                                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);
-
+                               EVASIMAGESINK_SET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo, esink);
+#ifdef USE_TBM_SURFACE
+                               GST_WARNING("register render callback [esink : %p, esink->eo : %x]", esink, esink->eo);
+                               EVASIMAGESINK_SET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo), esink);
+                               evas_object_geometry_get(esink->eo, &esink->eo_size.x, &esink->eo_size.y, &esink->eo_size.w, &esink->eo_size.h);
+                               GST_WARNING ("evas object size (x:%d, y:%d, w:%d, h:%d)", esink->eo_size.x, esink->eo_size.y, esink->eo_size.w, esink->eo_size.h);
+#endif
+#ifdef USE_FIMCC
                                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);
+#endif
+                               GST_DEBUG("Evas Image Object(%x) is set", esink->eo);
+                               esink->is_evas_object_size_set = FALSE;
                                esink->object_show = TRUE;
+                               esink->update_visibility = UPDATE_TRUE;
+                               if (esink->epipe) {
+                                       r = ecore_pipe_write (esink->epipe, &esink->update_visibility, SIZE_FOR_UPDATE_VISIBILITY);
+                                       if (r == EINA_FALSE)  {
+                                               GST_WARNING ("Failed to ecore_pipe_write() for updating visibility\n");
+                                       }
+                               }
                        }
                } else {
                        GST_ERROR ("Cannot set evas-object property: value is not an evas image object");
@@ -501,20 +1316,87 @@ gst_evas_image_sink_set_property (GObject *object, guint prop_id, const GValue *
                break;
 
        case PROP_EVAS_OBJECT_SHOW:
+       {
+               Eina_Bool r;
                esink->object_show = g_value_get_boolean (value);
                if( !is_evas_image_object(esink->eo) ) {
                        GST_WARNING ("Cannot apply visible(show-object) property: cannot get an evas object\n");
                        break;
                }
-               if(!esink->object_show) {
-                       evas_object_hide(esink->eo);
-                       GST_INFO ("object hide..");
-               } else {
-                       evas_object_show(esink->eo);
-                       GST_INFO ("object show..");
+               esink->update_visibility = UPDATE_TRUE;
+               GST_LOG("esink->update_visibility : %d", esink->update_visibility);
+               if (esink->epipe) {
+                       r = ecore_pipe_write (esink->epipe, &esink->update_visibility, SIZE_FOR_UPDATE_VISIBILITY);
+                       if (r == EINA_FALSE)  {
+                               GST_WARNING ("Failed to ecore_pipe_write() for updating visibility)\n");
+                       }
+               }
+               break;
+       }
+#ifdef USE_TBM_SURFACE
+       case PROP_ROTATE_ANGLE:
+       {
+               int rotate = 0;
+               rotate = g_value_get_int (value);
+               switch(rotate)
+               {
+                       case DEGREE_0:
+                               esink->rotate_angle = 0;
+                               break;
+                       case DEGREE_90:
+                               esink->rotate_angle = 90;
+                               break;
+                       case DEGREE_180:
+                               esink->rotate_angle = 180;
+                               break;
+                       case DEGREE_270:
+                               esink->rotate_angle = 270;
+                               break;
+                       default:
+                               break;
                }
+               GST_INFO("update rotate_angle : %d", esink->rotate_angle);
                break;
+       }
+       case PROP_DISPLAY_GEOMETRY_METHOD:
+       {
+               Eina_Bool r;
+               guint geometry = g_value_get_int (value);
+               if (esink->display_geometry_method != geometry) {
+                       esink->display_geometry_method = geometry;
+                       GST_INFO_OBJECT (esink, "Overlay geometry method update, display_geometry_method(%d)", esink->display_geometry_method);
+               }
 
+               g_mutex_lock(esink->display_buffer_lock);
+
+               if(esink->cur_index!=-1 && esink->epipe)
+               {
+                       GST_WARNING("apply property esink->cur_index =%d",esink->cur_index);
+                       esink->displaying_buffer[esink->cur_index].ref_count++;
+                       gst_buffer_ref(esink->displaying_buffer[esink->cur_index].buffer);
+                       esink->sent_buffer_cnt++;
+                       r = ecore_pipe_write (esink->epipe, &esink->cur_index, SIZE_FOR_NATIVE_INDEX);
+
+                       if (r == EINA_FALSE)  {
+                              GST_WARNING("ecore_pipe_write fail");
+                                 esink->displaying_buffer[esink->cur_index].ref_count--;
+                                 gst_buffer_unref(esink->displaying_buffer[esink->cur_index].buffer);
+                                 esink->sent_buffer_cnt--;
+                     }
+               }
+               g_mutex_unlock(esink->display_buffer_lock);
+               break;
+       }
+       case PROP_ENABLE_FLUSH_BUFFER:
+               esink->enable_flush_buffer = g_value_get_boolean(value);
+               break;
+       case PROP_FLIP:
+       {
+               esink->flip = g_value_get_int(value);
+               GST_INFO("update flip : %d", esink->flip);
+               break;
+       }
+#endif
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -535,6 +1417,20 @@ gst_evas_image_sink_get_property (GObject *object, guint prop_id, GValue *value,
        case PROP_EVAS_OBJECT_SHOW:
                g_value_set_boolean (value, esink->object_show);
                break;
+#ifdef USE_TBM_SURFACE
+       case PROP_ROTATE_ANGLE:
+               g_value_set_int (value, esink->rotate_angle);
+               break;
+       case PROP_DISPLAY_GEOMETRY_METHOD:
+               g_value_set_int (value, esink->display_geometry_method);
+               break;
+       case PROP_ENABLE_FLUSH_BUFFER:
+               g_value_set_boolean(value, esink->enable_flush_buffer);
+               break;
+       case PROP_FLIP:
+               g_value_set_int(value, esink->flip);
+               break;
+#endif
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -547,6 +1443,8 @@ gst_evas_image_sink_set_caps (GstBaseSink *base_sink, GstCaps *caps)
        int r;
        int w, h;
        GstEvasImageSink *esink = GST_EVASIMAGESINK (base_sink);
+       GstStructure *structure = NULL;
+       guint32 format = 0;
 
        esink->is_evas_object_size_set = FALSE;
        r = evas_image_sink_get_size_from_caps (caps, &w, &h);
@@ -555,6 +1453,29 @@ gst_evas_image_sink_set_caps (GstBaseSink *base_sink, GstCaps *caps)
                esink->h = h;
                GST_DEBUG ("set size w(%d), h(%d)", w, h);
        }
+
+       structure = gst_caps_get_structure (caps, 0);
+       if (!structure) {
+               return FALSE;
+       }
+
+       if (!gst_structure_get_fourcc (structure, "format", &format)) {
+               GST_DEBUG ("format(dst) is not set...it may be rgb series");
+       }
+
+       GST_DEBUG_OBJECT(esink, "source color format is %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (format));
+
+#ifdef USE_TBM_SURFACE
+       if (format == GST_MAKE_FOURCC('S','N','1','2') || format == GST_MAKE_FOURCC('N','V','1','2') ) {
+               esink->tbm_surface_format = TBM_FORMAT_NV12;
+       } else if (format == GST_MAKE_FOURCC('I','4','2','0')){
+               esink->tbm_surface_format = TBM_FORMAT_YUV420;
+       } else {
+               GST_ERROR("cannot parse fourcc format from caps.");
+               return FALSE;
+       }
+#endif
+
        return TRUE;
 }
 
@@ -564,35 +1485,485 @@ gst_evas_image_sink_show_frame (GstVideoSink *video_sink, GstBuffer *buf)
        GstEvasImageSink *esink = GST_EVASIMAGESINK (video_sink);
        Eina_Bool r;
 
+       GST_LOG("[ENTER] show frame");
+#ifdef USE_TBM_SURFACE
+       if (!gst_evas_image_sink_ref_count (buf))
+       {
+               GST_WARNING("ref count is 0.. skip show frame");
+               return GST_FLOW_OK;
+       }
+#endif
        g_mutex_lock (instance_lock);
+#ifdef USE_FIMCC
        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));
+       } else if (esink->present_data_addr != DO_RENDER_FROM_FIMC) {
+               GST_WARNING ("skip rendering this buffer, present_data_addr:%d, DO_RENDER_FROM_FIMC:%d", esink->present_data_addr, DO_RENDER_FROM_FIMC);
                g_mutex_unlock (instance_lock);
-               return;
+               return GST_FLOW_OK;
        }
+#endif
        if (!esink->epipe) {
-               esink->epipe = ecore_pipe_add (evas_image_sink_cb_pipe, esink);
+               esink->epipe = ecore_pipe_add ((Ecore_Pipe_Cb)evas_image_sink_cb_pipe, esink);
                if (!esink->epipe) {
                        GST_ERROR ("ecore-pipe create failed");
+                       g_mutex_unlock (instance_lock);
                        return GST_FLOW_ERROR;
                }
+               GST_DEBUG("ecore-pipe create success");
        }
-       if (esink->object_show) {
+#ifdef USE_TBM_SURFACE
+       int i = 0;
+       int index = -1;
+       SCMN_IMGB *scmn_imgb = NULL;
+       gboolean exist_bo = FALSE;
+
+       GST_LOG ("BUF: gst_buf= %p ts= %" GST_TIME_FORMAT " size= %lu,  mallocdata= %p",
+               buf, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_SIZE (buf), GST_BUFFER_MALLOCDATA(buf));
+
+       if(esink->tbm_surface_format == TBM_FORMAT_NV12) {
+               /* get received buffer informations */
+               scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
+               if (!scmn_imgb) {
+                       GST_WARNING("scmn_imgb is NULL. Skip..." );
+                       g_mutex_unlock (instance_lock);
+                       return GST_FLOW_OK;
+               }
+               if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_TIZEN_BUFFER)
+               {
+                       /* check whether bo is new or not */
+                       for(i=0; i<NATIVE_BUFFER_NUM; i++)
+                       {
+                               if(esink->displaying_buffer[i].bo==scmn_imgb->bo[0])
+                               {
+                                       GST_DEBUG("it is already saved bo %p (index num : %d)", esink->displaying_buffer[i].bo, i);
+                                       index = i;
+                                       exist_bo = TRUE;
+                                       break;
+                               }
+                               else
+                                       exist_bo = FALSE;
+                       }
+                       /* keep bo */
+                       if(!exist_bo)
+                       {
+                               /* find empty buffer space for indexing */
+                               for(i=0; i<NATIVE_BUFFER_NUM; i++)
+                               {
+                                       if(!esink->displaying_buffer[i].bo)
+                                       {
+                                               index = i;
+                                               break;
+                                       }
+                               }
+                               if(index!=-1)
+                               {
+                                       /* keep informations */
+                                       esink->displaying_buffer[index].buffer = buf;
+                                       esink->displaying_buffer[index].bo = scmn_imgb->bo[0];
+                                       GST_WARNING("TBM bo %p / gst_buf %p", esink->displaying_buffer[index].bo, esink->displaying_buffer[index].buffer);
+
+                                       /* create new tbm surface */
+                                       esink->displaying_buffer[index].tbm_surf = tbm_surface_internal_create_with_bos(esink->w, esink->h,
+                                         TBM_FORMAT_NV12, esink->displaying_buffer[index].bo, TBM_BO_DEFAULT);
+                                       if(!esink->displaying_buffer[index].tbm_surf)
+                                       {
+                                               GST_WARNING("there is no tbm surface.. bo : %p,  gst_buf : %p", esink->displaying_buffer[index].bo, esink->displaying_buffer[index].buffer);
+                                               g_mutex_unlock (instance_lock);
+                                               return GST_FLOW_OK;
+                                       }
+
+                                       GST_WARNING("create tbm surface : %p", esink->displaying_buffer[index].tbm_surf);
+                               }
+                       }
+                       /* because it has same bo, use existing tbm surface */
+                       else
+                       {
+                               if(index!=-1)
+                               {
+                                       esink->displaying_buffer[index].buffer = buf;
+                                       GST_DEBUG("existing tbm surface %p.. bo %p,  gst_buf %p", esink->displaying_buffer[index].tbm_surf, esink->displaying_buffer[index].bo, esink->displaying_buffer[index].buffer);
+                                       exist_bo = FALSE;
+                               }
+                       }
+
+                       /* if it couldn't find proper index */
+                       if(index == -1)
+                               GST_WARNING("all spaces are using!!!");
+                       else
+                               GST_DEBUG("selected buffer index %d", index);
+
+               }
+               else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_FLUSH_BUFFER)
+               {
+                       /* flush buffer, we will copy last buffer to keep image data and reset buffer list */
+                       GST_WARNING_OBJECT(esink, "FLUSH_BUFFER: gst_buf= %p ts= %" GST_TIME_FORMAT " size= %lu,  mallocdata= %p",
+                       buf, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_SIZE (buf), GST_BUFFER_MALLOCDATA(buf));
+                       gst_buffer_ref (buf);
+                       if (gst_esink_make_flush_buffer(esink))
+                               GST_WARNING("made flush buffer");
+                       gst_buffer_unref (buf);
+               }
+               else
+               {
+                       GST_ERROR("it is not TBM buffer.. %d", scmn_imgb->buf_share_method);
+               }
+       } else if(esink->tbm_surface_format == TBM_FORMAT_YUV420) {
+               static int skip_count_i420=0;
+               if(esink->sent_buffer_cnt >= MAX_ECOREPIPE_BUFFER_CNT) {
+                       if(!(skip_count_i420++%20)) {
+                               GST_WARNING("[%d]EA buffer was already sent to ecore pipe, and %d frame skipped", esink->sent_buffer_cnt,skip_count_i420);
+                       }
+                       g_mutex_unlock (instance_lock);
+                       return GST_FLOW_OK;
+               }
+
+               if(!esink->is_buffer_allocated) {
+                       /* Allocate TBM buffer for non-zero copy case */
+                       if(!gst_evas_image_sink_allocate_source_buffer(esink)) {
+                               GST_ERROR_OBJECT(esink, "Buffer allocation failed");
+                               g_mutex_unlock (instance_lock);
+                               return GST_FLOW_ERROR;
+                       }
+                       esink->is_buffer_allocated = TRUE;
+               }
+
+               skip_count_i420 = 0; //for skip log in I420
+
+               /* check whether bo is new or not */
+               for(i=0; i<NATIVE_BUFFER_NUM; i++) {
+                       if(esink->displaying_buffer[i].bo == esink->src_buffer_info[esink->src_buf_idx].bo) {
+                               GST_DEBUG_OBJECT(esink, "it is already saved bo %p (index num : %d)", esink->displaying_buffer[i].bo, i);
+                               index = i;
+                               exist_bo = TRUE;
+                               break;
+                       }
+                       else
+                               exist_bo = FALSE;
+               }
+
+               /* keep bo */
+               if(!exist_bo) {
+                       /* find empty buffer space for indexing */
+                       for(i=0; i<NATIVE_BUFFER_NUM; i++) {
+                               if(!esink->displaying_buffer[i].bo) {
+                                       index = i;
+                                       break;
+                               }
+                       }
+
+                       if(index!=-1) {
+                               /* keep informations */
+                               esink->displaying_buffer[index].bo = esink->src_buffer_info[esink->src_buf_idx].bo;
+                               esink->displaying_buffer[index].tbm_surf = esink->src_buffer_info[esink->src_buf_idx].tbm_surf;
+
+                               GST_DEBUG_OBJECT(esink, "gst_buf %p, TBM bo %p.. gst_buf vaddr %p .. src data size(%lu)",
+                                       buf, esink->displaying_buffer[index].bo, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf));
+
+                               memcpy(esink->src_buffer_info[esink->src_buf_idx].usr_addr, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf));
+                       }
+               } else {
+                       /* because it has same bo, use existing tbm surface */
+                       if(index!=-1) {
+                               memcpy(esink->src_buffer_info[esink->src_buf_idx].usr_addr, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf));
+
+                               GST_DEBUG_OBJECT(esink, "existing tbm surface %p.. gst_buf %p, bo %p,  gst_buf vaddr %p",
+                                       esink->displaying_buffer[index].tbm_surf, buf, esink->displaying_buffer[index].bo, GST_BUFFER_DATA(buf));
+                               exist_bo = FALSE;
+                       }
+               }
+
+               /* if it couldn't find proper index */
+               if(index == -1)
+                       GST_WARNING_OBJECT(esink, "all spaces are being used!!!");
+               else
+                       GST_DEBUG_OBJECT(esink, "selected buffer index %d", index);
+
+       } else {
+               GST_ERROR_OBJECT(esink, "unsupported color format");
+               g_mutex_unlock (instance_lock);
+               return GST_FLOW_ERROR;
+       }
+#endif
+       if (esink->object_show && index != -1) {
+#ifdef USE_FIMCC
                gst_buffer_ref (buf);
-               __ta__("evasimagesink ecore_pipe_write", r = ecore_pipe_write (esink->epipe, &buf, sizeof (GstBuffer *)););
+               r = ecore_pipe_write (esink->epipe, &buf, sizeof (GstBuffer *));
                if (r == EINA_FALSE)  {
+                       //add error handling
+                       GST_WARNING("ecore_pipe_write fail");
                        gst_buffer_unref (buf);
                }
-               GST_DEBUG ("after ecore_pipe_write()");
+#endif
+#ifdef USE_TBM_SURFACE
+               int old_curidx=esink->cur_index ;
+               static int skip_count=0;
+               g_mutex_lock(esink->display_buffer_lock);
+
+               if(esink->tbm_surface_format == TBM_FORMAT_NV12 && scmn_imgb->buf_share_method != BUF_SHARE_METHOD_FLUSH_BUFFER) {
+                       if (esink->sent_buffer_cnt < MAX_ECOREPIPE_BUFFER_CNT) {
+                               GST_LOG("[show_frame] before refcount : %d .. gst_buf : %p", gst_evas_image_sink_ref_count (buf), buf);
+                               gst_buffer_ref (buf);
+                               esink->displaying_buffer[index].ref_count++;
+                               esink->cur_index = index;
+                               GST_LOG("index %d set refcount increase as %d", index,esink->displaying_buffer[index].ref_count);
+                               GST_LOG("[show_frame] after refcount : %d .. gst_buf : %p", gst_evas_image_sink_ref_count (buf), buf);
+
+                               /* Print debug log for 8 frame */
+                               if(esink->debuglog_cnt_showFrame > 0)
+                               {
+                                       GST_WARNING("(%d) ecore_pipe_write index[%d]  gst_buf : %p", DEBUGLOG_DEFAULT_COUNT-(esink->debuglog_cnt_showFrame),
+                                               esink->cur_index, esink->displaying_buffer[esink->cur_index].buffer);
+                                       esink->debuglog_cnt_showFrame--;
+                               }
+
+                               esink->sent_buffer_cnt++;
+                               skip_count =0 ;
+
+                               r = ecore_pipe_write (esink->epipe, &esink->cur_index , SIZE_FOR_NATIVE_INDEX);
+
+                               if (r == EINA_FALSE)  {
+                                       GST_LOG("[show_frame] before refcount : %d .. gst_buf : %p", gst_evas_image_sink_ref_count (buf), buf);
+                                       esink->cur_index = old_curidx;
+                                       if(esink->displaying_buffer[index].ref_count)
+                                       {
+                                               esink->displaying_buffer[index].ref_count--;
+                                               esink->sent_buffer_cnt--;
+                                               gst_buffer_unref(buf);
+                                               GST_ERROR("finish unreffing");
+                                       }
+                               }
+                       } else {
+                               /* If buffer count which is sent to ecore pipe, is upper 3, Print Error log */
+                               if(!(skip_count++%20)) {
+                                       GST_WARNING("[%d]EA buffer was already sent to ecore pipe, and %d frame skipped", esink->sent_buffer_cnt,skip_count);
+                               }
+                       }
+               } else if (esink->tbm_surface_format == TBM_FORMAT_YUV420) {
+                       esink->cur_index = index;
+                       GST_LOG("index %d", index);
+                       GST_LOG("[show_frame] gst_buf vaddr %p", esink->src_buffer_info[esink->src_buf_idx].usr_addr);
+
+                       /* Print debug log for 8 frame */
+                       if(esink->debuglog_cnt_showFrame > 0)
+                       {
+                               GST_WARNING("(%d) ecore_pipe_write :  index[%d], bo[%p], tbm_surf[%p], gst_buf[%p], gst_buf vaddr [%p]", DEBUGLOG_DEFAULT_COUNT-(esink->debuglog_cnt_showFrame),
+                                       esink->cur_index, esink->displaying_buffer[index].bo, esink->displaying_buffer[index].tbm_surf, buf, esink->src_buffer_info[esink->src_buf_idx].usr_addr);
+                               esink->debuglog_cnt_showFrame--;
+                       }
+
+                       esink->sent_buffer_cnt++;
+
+                       esink->src_buf_idx++;
+                   r = ecore_pipe_write (esink->epipe, &esink->cur_index , SIZE_FOR_NATIVE_INDEX);
+
+                       if (r == EINA_FALSE)  {
+                               esink->cur_index = old_curidx;
+                               esink->sent_buffer_cnt--;
+                               esink->src_buf_idx--;
+                               GST_ERROR("ecore_pipe_write is failed. index[%d], bo[%p], tbm_surf[%p], gst_buf vaddr [%p]",
+                                       index, esink->displaying_buffer[index].bo, esink->displaying_buffer[index].tbm_surf, esink->src_buffer_info[esink->src_buf_idx].usr_addr);
+                       }
+                       esink->src_buf_idx = esink->src_buf_idx % SOURCE_BUFFER_NUM;
+               }
+
+               g_mutex_unlock(esink->display_buffer_lock);
+#endif
+               GST_DEBUG ("ecore_pipe_write() was called with gst_buf= %p..  gst_buf Vaddr=%p, mallocdata= %p", buf, GST_BUFFER_DATA(buf), GST_BUFFER_MALLOCDATA(buf));
        } else {
-               GST_DEBUG ("skip ecore_pipe_write()");
+               GST_WARNING ("skip ecore_pipe_write(). becuase of esink->object_show(%d) index(%d)", esink->object_show, index);
        }
        g_mutex_unlock (instance_lock);
+       GST_DEBUG ("Leave");
        return GST_FLOW_OK;
 }
 
+#ifdef USE_TBM_SURFACE
+static GstFlowReturn
+gst_esink_epipe_reset(GstEvasImageSink *esink)
+{
+       if (esink == NULL) {
+               GST_ERROR("handle is NULL");
+               return GST_FLOW_ERROR;
+       }
+
+       if (esink->epipe) {
+               GST_DEBUG("ecore-pipe will delete");
+               ecore_pipe_del (esink->epipe);
+               esink->epipe = NULL;
+       }
+
+       if (!esink->epipe) {
+               esink->epipe = ecore_pipe_add ((Ecore_Pipe_Cb)evas_image_sink_cb_pipe, esink);
+               if (!esink->epipe) {
+                       GST_ERROR ("ecore-pipe create failed");
+                       return GST_FLOW_ERROR;
+               }
+               GST_DEBUG("ecore-pipe create success");
+       }
+
+       return GST_FLOW_OK;
+}
+
+
+static gboolean gst_esink_make_flush_buffer(GstEvasImageSink *esink)
+{
+       GstEvasImageFlushBuffer *flush_buffer = NULL;
+       GstEvasImageDisplayingBuffer *display_buffer = NULL;
+       int size = 0;
+       tbm_bo bo;
+       tbm_bo_handle vaddr_src;
+       tbm_bo_handle vaddr_dst;
+       GstFlowReturn ret=GST_FLOW_OK;
+       int src_size = 0;
+
+       if (esink == NULL) {
+               GST_ERROR("handle is NULL");
+               return FALSE;
+       }
+
+       if (esink->cur_index == -1) {
+               GST_WARNING_OBJECT(esink, "there is no remained buffer");
+               return FALSE;
+       }
+
+       if(esink->flush_buffer)
+               _release_flush_buffer(esink);
+
+       /* malloc buffer */
+       flush_buffer = (GstEvasImageFlushBuffer *)malloc(sizeof(GstEvasImageFlushBuffer));
+       if (flush_buffer == NULL) {
+               GST_ERROR_OBJECT(esink, "GstEvasImageFlushBuffer alloc failed");
+               return FALSE;
+       }
+
+       memset(flush_buffer, 0x0, sizeof(GstEvasImageFlushBuffer));
+
+       display_buffer = &(esink->displaying_buffer[esink->cur_index]);
+       GST_WARNING_OBJECT(esink, "cur_index [%d]",
+                                                                 esink->cur_index);
+       if(!display_buffer || !display_buffer->bo)
+       {
+               GST_WARNING("display_buffer(%p) or bo (%p) is NULL!!", display_buffer, display_buffer->bo);
+               goto FLUSH_BUFFER_FAILED;
+       }
+
+       /* create tbm surface */
+       flush_buffer->tbm_surf = tbm_surface_create(esink->w, esink->h, TBM_FORMAT_NV12);
+
+       if(!flush_buffer->tbm_surf)
+       {
+               GST_ERROR("tbm_surf is NULL!!");
+               goto FLUSH_BUFFER_FAILED;
+       }
+
+       /* get bo and size */
+       bo = tbm_surface_internal_get_bo(flush_buffer->tbm_surf, 0);
+       size = tbm_bo_size(bo);
+       if(!bo || !size)
+       {
+               GST_ERROR("bo(%p), size(%d)", bo, size);
+               goto FLUSH_BUFFER_FAILED;
+       }
+       flush_buffer->bo = bo;
+
+       src_size = display_buffer->buffer->size;
+
+       vaddr_src = tbm_bo_map(display_buffer->bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
+       vaddr_dst = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
+       if (!vaddr_src.ptr || !vaddr_dst.ptr) {
+               GST_WARNING_OBJECT(esink, "get vaddr failed src %p, dst %p", vaddr_src.ptr, vaddr_dst.ptr);
+               if (vaddr_src.ptr) {
+                       tbm_bo_unmap(display_buffer->bo);
+               }
+               if (vaddr_dst.ptr) {
+                       tbm_bo_unmap(bo);
+               }
+               goto FLUSH_BUFFER_FAILED;
+       } else {
+               memset (vaddr_dst.ptr, 0x0, size);
+               GST_WARNING_OBJECT (esink, "tbm_bo_map(VADDR) finished, bo(%p), vaddr(%p)", bo, vaddr_dst.ptr);
+       }
+
+       /* copy buffer */
+       memcpy(vaddr_dst.ptr, vaddr_src.ptr, src_size);
+
+       tbm_bo_unmap(display_buffer->bo);
+       tbm_bo_unmap(bo);
+
+       GST_WARNING_OBJECT(esink, "copy done.. tbm surface : %p src_size : %d", flush_buffer->tbm_surf, src_size);
+
+       esink->flush_buffer = flush_buffer;
+
+       /* initialize buffer list */
+       if (esink->object_show)
+               esink->need_flush = TRUE;
+
+       ret = gst_esink_epipe_reset(esink);
+       if(ret) {
+              GST_ERROR_OBJECT(esink, "evas epipe reset ret=%d, need to check",ret);
+              return FALSE;
+       } else {
+              GST_ERROR_OBJECT(esink, "evas epipe reset success");
+       }
+
+       gst_evas_image_sink_reset(esink);
+
+
+       return TRUE;
+
+FLUSH_BUFFER_FAILED:
+       if (flush_buffer) {
+               if(flush_buffer->tbm_surf)
+               {
+                       tbm_surface_destroy(flush_buffer->tbm_surf);
+                       flush_buffer->tbm_surf = NULL;
+               }
+
+               free(flush_buffer);
+               flush_buffer = NULL;
+       }
+       return FALSE;
+}
+
+ static void _release_flush_buffer(GstEvasImageSink *esink)
+{
+       if (esink == NULL ||
+           esink->flush_buffer == NULL) {
+               GST_WARNING("handle is NULL");
+               return;
+       }
+
+       GST_WARNING_OBJECT(esink, "release FLUSH BUFFER start");
+       if (esink->flush_buffer->bo) {
+               esink->flush_buffer->bo = NULL;
+       }
+       if(esink->flush_buffer->tbm_surf) {
+               tbm_surface_destroy(esink->flush_buffer->tbm_surf);
+               esink->flush_buffer->tbm_surf = NULL;
+       }
+
+       GST_WARNING_OBJECT(esink, "release FLUSH BUFFER done");
+
+       free(esink->flush_buffer);
+       esink->flush_buffer = NULL;
+
+       return;
+}
+#endif
+#ifdef DUMP_IMG
+int util_write_rawdata(const char *file, const void *data, unsigned int size)
+{
+       FILE *fp;
+       fp = fopen(file, "wb");
+       if (fp == NULL)
+               return -1;
+       fwrite((char*)data, sizeof(char), size, fp);
+       fclose(fp);
+       return 0;
+}
+#endif
+
 static gboolean
 evas_image_sink_init (GstPlugin *evasimagesink)
 {
old mode 100644 (file)
new mode 100755 (executable)
index 1e2e19b..1633044
 #ifndef __GST_EVASIMAGESINK_H__
 #define __GST_EVASIMAGESINK_H__
 
+//#define USE_TBM_SURFACE
+#define USE_FIMCC
+
 #include <gst/gst.h>
 #include <gst/video/gstvideosink.h>
 #include <Evas.h>
 #include <Ecore.h>
-#include <mm_ta.h>
-
+#ifdef USE_TBM_SURFACE
+#include <tbm_surface.h>
+#include <tbm_bufmgr.h>
+#endif
 G_BEGIN_DECLS
 
 /* #defines don't like whitespacey bits */
@@ -46,7 +51,71 @@ G_BEGIN_DECLS
 
 typedef struct _GstEvasImageSink      GstEvasImageSink;
 typedef struct _GstEvasImageSinkClass GstEvasImageSinkClass;
+#ifdef USE_TBM_SURFACE
+typedef struct _GstEvasImageDisplayingBuffer GstEvasImageDisplayingBuffer;
+typedef struct _GstEvasImageFlushBuffer GstEvasImageFlushBuffer;
+typedef enum {
+       BUF_SHARE_METHOD_NONE = -1,
+       BUF_SHARE_METHOD_PADDR = 0,
+       BUF_SHARE_METHOD_FD,
+       BUF_SHARE_METHOD_TIZEN_BUFFER,
+       BUF_SHARE_METHOD_FLUSH_BUFFER
+} buf_share_method_t;
+
+enum {
+    DEGREE_0 = 0,
+    DEGREE_90,
+    DEGREE_180,
+    DEGREE_270,
+    DEGREE_NUM,
+};
+
+enum {
+    DISP_GEO_METHOD_LETTER_BOX = 0,
+    DISP_GEO_METHOD_ORIGIN_SIZE,
+    DISP_GEO_METHOD_FULL_SCREEN,
+    DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
+    DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX,
+    DISP_GEO_METHOD_CUSTOM_DST_ROI,
+    DISP_GEO_METHOD_NUM,
+};
+
+enum {
+       FLIP_NONE = 0,
+       FLIP_HORIZONTAL,
+       FLIP_VERTICAL,
+       FLIP_BOTH,
+       FLIP_NUM
+};
 
+struct buffer_info {
+       uint64_t usr_addr;
+       uint64_t size;
+       void *bo;
+       tbm_surface_h tbm_surf;
+};
+
+/* _GstEvasDisplayingBuffer
+ *
+ * buffer              : manage ref count by got index through comparison
+ * bo                  : compare with buffer from codec for getting index
+ * n_buffer            : compare with buffer from evas for getting index
+ * ref_count   : decide whether it unref buffer or not in gst_evas_image_sink_fini/reset
+ */
+struct _GstEvasImageDisplayingBuffer {
+       GstBuffer *buffer;
+       void *bo;
+       tbm_surface_h tbm_surf;
+       int ref_count;
+};
+
+struct _GstEvasImageFlushBuffer {
+       void *bo;
+       tbm_surface_h tbm_surf;
+};
+#define NATIVE_BUFFER_NUM 20
+#define SOURCE_BUFFER_NUM 8
+#endif
 struct _GstEvasImageSink
 {
        GstVideoSink element;
@@ -56,12 +125,37 @@ struct _GstEvasImageSink
        Evas_Coord w;
        Evas_Coord h;
        gboolean object_show;
+       gchar update_visibility;
        gboolean gl_zerocopy;
 
        GstBuffer *oldbuf;
 
        gboolean is_evas_object_size_set;
        guint present_data_addr;
+#ifdef USE_TBM_SURFACE
+       GMutex *display_buffer_lock;
+       GMutex *flow_lock;
+       GstEvasImageDisplayingBuffer displaying_buffer[NATIVE_BUFFER_NUM];
+       GstVideoRectangle eo_size;
+       gboolean use_ratio;
+       guint rotate_angle;
+       guint display_geometry_method;
+       guint flip;
+       GstBuffer *prev_buf;
+       gint prev_index;
+       gint cur_index;
+       gboolean need_flush;
+       gboolean enable_flush_buffer;
+       GstEvasImageFlushBuffer *flush_buffer;
+       gint sent_buffer_cnt;
+       gint debuglog_cnt_showFrame;
+       gint debuglog_cnt_ecoreCbPipe;
+
+       tbm_format tbm_surface_format;
+       struct buffer_info src_buffer_info[NATIVE_BUFFER_NUM];
+       guint src_buf_idx;
+       gboolean is_buffer_allocated;
+#endif
 };
 
 struct _GstEvasImageSinkClass
diff --git a/evaspixmapsink/Makefile.am b/evaspixmapsink/Makefile.am
new file mode 100644 (file)
index 0000000..4caa9d5
--- /dev/null
@@ -0,0 +1,14 @@
+plugin_LTLIBRARIES = libgstevaspixmapsink.la
+
+libgstevaspixmapsink_la_SOURCES = evaspixmapsink.c
+libgstevaspixmapsink_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS) $(EFL_CFLAGS) \
+       $(XFIXES_CFLAGS) $(DRI2PROTO_CFLAGS) $(DRI2_CFLAGS) $(X11_CFLAGS) $(XDAMAGE_CFLAGS) $(XV_CFLAGS) $(TBM_CFLAGS) $(DRM_CFLAGS) $(DRM_DEVEL_CFLAGS)
+libgstevaspixmapsink_la_LIBADD = \
+       $(GST_LIBS) -lgstvideo-$(GST_MAJORMINOR) -lgstinterfaces-$(GST_MAJORMINOR) \
+       $(X_LIBS) $(XVIDEO_LIBS) $(XSHM_LIBS) $(LIBM) \
+       $(EFL_LIBS) \
+       $(XFIXES_LIBS) $(DRI2PROTO_LIBS) $(DRI2_LIBS) $(X11_LIBS) $(XDAMAGE_LIBS) $(XV_LIBS) $(TBM_LIBS) $(DRM_LIBS) $(DRM_DEVEL_LIBS)
+libgstevaspixmapsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstxvimagesink_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = evaspixmapsink.h
diff --git a/evaspixmapsink/evaspixmapsink.c b/evaspixmapsink/evaspixmapsink.c
new file mode 100755 (executable)
index 0000000..3e25891
--- /dev/null
@@ -0,0 +1,4921 @@
+/*
+ * EvasPixmapSink
+ *
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sangchul Lee <sc11.lee@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
+
+/* Our interfaces */
+#include <gst/interfaces/navigation.h>
+#include <gst/interfaces/colorbalance.h>
+#include <gst/interfaces/propertyprobe.h>
+/* Helper functions */
+#include <gst/video/video.h>
+
+/* Object header */
+#include "evaspixmapsink.h"
+
+#include <time.h>
+
+/* Samsung extension headers */
+/* For xv extension header for buffer transfer (output) */
+#include "xv_types.h"
+
+/* headers for drm */
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <X11/Xmd.h>
+#include <dri2/dri2.h>
+#include <libdrm/drm.h>
+
+/* max channel count *********************************************************/
+#define SCMN_IMGB_MAX_PLANE         (4)
+
+/* image buffer definition ***************************************************
+
+    +------------------------------------------+ ---
+    |                                          |  ^
+    |     a[], p[]                             |  |
+    |     +---------------------------+ ---    |  |
+    |     |                           |  ^     |  |
+    |     |<---------- w[] ---------->|  |     |  |
+    |     |                           |  |     |  |
+    |     |                           |        |
+    |     |                           |  h[]   |  e[]
+    |     |                           |        |
+    |     |                           |  |     |  |
+    |     |                           |  |     |  |
+    |     |                           |  v     |  |
+    |     +---------------------------+ ---    |  |
+    |                                          |  v
+    +------------------------------------------+ ---
+
+    |<----------------- s[] ------------------>|
+*/
+
+typedef struct
+{
+       /* width of each image plane */
+       int w[SCMN_IMGB_MAX_PLANE];
+       /* height of each image plane */
+       int h[SCMN_IMGB_MAX_PLANE];
+       /* stride of each image plane */
+       int s[SCMN_IMGB_MAX_PLANE];
+       /* elevation of each image plane */
+       int e[SCMN_IMGB_MAX_PLANE];
+       /* user space address of each image plane */
+       void *a[SCMN_IMGB_MAX_PLANE];
+       /* physical address of each image plane, if needs */
+       void *p[SCMN_IMGB_MAX_PLANE];
+       /* color space type of image */
+       int cs;
+       /* left postion, if needs */
+       int x;
+       /* top position, if needs */
+       int y;
+       /* to align memory */
+       int __dummy2;
+       /* arbitrary data */
+       int data[16];
+       /* dma buf fd */
+       int dma_buf_fd[SCMN_IMGB_MAX_PLANE];
+       /* buffer share method */
+       int buf_share_method;
+       /* Y plane size in case of ST12 */
+       int y_size;
+       /* UV plane size in case of ST12 */
+       int uv_size;
+       /* Tizen buffer object */
+       void *bo[SCMN_IMGB_MAX_PLANE];
+       /* JPEG data */
+       void *jpeg_data;
+       /* JPEG size */
+       int jpeg_size;
+       /* TZ memory buffer */
+       int tz_enable;
+} SCMN_IMGB;
+
+/* Debugging category */
+#include <gst/gstinfo.h>
+GST_DEBUG_CATEGORY_STATIC (gst_debug_evaspixmapsink);
+#define GST_CAT_DEFAULT gst_debug_evaspixmapsink
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
+
+enum {
+    UPDATE_FALSE,
+    UPDATE_TRUE
+};
+
+enum {
+    DEGREE_0,
+    DEGREE_90,
+    DEGREE_180,
+    DEGREE_270,
+    DEGREE_NUM,
+};
+
+enum {
+    DISP_GEO_METHOD_LETTER_BOX = 0,
+    DISP_GEO_METHOD_ORIGIN_SIZE,
+    DISP_GEO_METHOD_FULL_SCREEN,
+    DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
+    DISP_GEO_METHOD_CUSTOM_ROI,
+    DISP_GEO_METHOD_NUM,
+};
+
+enum {
+    FLIP_NONE = 0,
+    FLIP_HORIZONTAL,
+    FLIP_VERTICAL,
+    FLIP_BOTH,
+    FLIP_NUM,
+};
+
+#define DEF_DISPLAY_GEOMETRY_METHOD                     DISP_GEO_METHOD_LETTER_BOX
+#define DEF_DISPLAY_FLIP                                FLIP_NONE
+#define GST_TYPE_EVASPIXMAPSINK_FLIP                    (gst_evaspixmapsink_flip_get_type())
+#define GST_TYPE_EVASPIXMAPSINK_ROTATE_ANGLE            (gst_evaspixmapsink_rotate_angle_get_type())
+#define GST_TYPE_EVASPIXMAPSINK_DISPLAY_GEOMETRY_METHOD (gst_evaspixmapsink_display_geometry_method_get_type())
+#define SIZE_FOR_UPDATE_VISIBILITY                      sizeof(gchar)
+#define EPIPE_REQUEST_LIMIT                             20
+
+#ifdef DUMP_IMG
+int util_write_rawdata (const char *file, const void *data, unsigned int size);
+typedef struct _BufferInfo
+{
+    Display *dpy;
+    Pixmap   pixmap;
+    int      width;
+    int      height;
+
+    /* Dri2 */
+    int         drm_fd;
+    tbm_bufmgr  bufmgr;
+    void       *virtual;
+    DRI2Buffer *dri2_buffers;
+    tbm_bo bo;
+} BufferInfo;
+
+static BufferInfo *g_bufinfo[NUM_OF_PIXMAP];
+void * gst_evaspixmapsink_get_buffer (Display *dpy, Pixmap pixmap, int width, int height, int i);
+void gst_evaspixmapsink_free_buffer (int i);
+static Bool gst_evaspixmapsink_init_dri2 (BufferInfo *bufinfo);
+int g_cnt;
+#endif
+
+/* macro ******************************************************/
+#define EVASPIXMAPSINK_SET_PIXMAP_ID_TO_GEM_INFO( x_evaspixmapsink, x_pixmap_id ) \
+do \
+{ \
+       int i = 0; \
+       XV_DATA_PTR data = (XV_DATA_PTR)x_evaspixmapsink->evas_pixmap_buf->xvimage->data; \
+       if (data->YBuf > 0) { \
+               for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
+                       if (evaspixmapsink->gem_info[i].gem_name == data->YBuf) { \
+                               evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
+                               GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(YBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
+                               break; \
+                       } \
+               } \
+       } \
+       if (data->CbBuf > 0) { \
+               for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
+                       if (evaspixmapsink->gem_info[i].gem_name == data->CbBuf) { \
+                               evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
+                               GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(CbBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
+                               break; \
+                       } \
+               } \
+       } \
+       if (data->CrBuf > 0) { \
+               for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
+                       if (evaspixmapsink->gem_info[i].gem_name == data->CrBuf) { \
+                               evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
+                               GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(CrBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
+                               break; \
+                       } \
+               } \
+       } \
+}while(0)
+
+#define EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object, x_usr_data ) \
+do \
+{ \
+       evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event, x_usr_data); \
+       evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event, x_usr_data); \
+       evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_SHOW, evas_callback_show_event, x_usr_data); \
+       evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_HIDE, evas_callback_hide_event, x_usr_data); \
+}while(0)
+
+#define EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object ) \
+do \
+{ \
+       evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event); \
+       evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event); \
+       evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_SHOW, evas_callback_show_event); \
+       evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_HIDE, evas_callback_hide_event); \
+}while(0)
+
+static GType
+gst_evaspixmapsink_flip_get_type(void)
+{
+       static GType evaspixmapsink_flip_type = 0;
+       static const GEnumValue flip_type[] = {
+               { FLIP_NONE,       "Flip NONE", "FLIP_NONE"},
+               { FLIP_HORIZONTAL, "Flip HORIZONTAL", "FLIP_HORIZONTAL"},
+               { FLIP_VERTICAL,   "Flip VERTICAL", "FLIP_VERTICAL"},
+               { FLIP_BOTH,       "Flip BOTH", "FLIP_BOTH"},
+               { FLIP_NUM, NULL, NULL},
+       };
+
+       if (!evaspixmapsink_flip_type) {
+               evaspixmapsink_flip_type = g_enum_register_static("GstEvasPixmapSinkFlipType", flip_type);
+       }
+
+       return evaspixmapsink_flip_type;
+}
+
+static GType
+gst_evaspixmapsink_rotate_angle_get_type(void)
+{
+       static GType evaspixmapsink_rotate_angle_type = 0;
+       static const GEnumValue rotate_angle_type[] = {
+               { 0, "No rotate", "DEGREE_0"},
+               { 1, "Rotate 90 degree", "DEGREE_90"},
+               { 2, "Rotate 180 degree", "DEGREE_180"},
+               { 3, "Rotate 270 degree", "DEGREE_270"},
+               { 4, NULL, NULL},
+       };
+
+       if (!evaspixmapsink_rotate_angle_type) {
+               evaspixmapsink_rotate_angle_type = g_enum_register_static("GstEvasPixmapSinkRotateAngleType", rotate_angle_type);
+       }
+
+       return evaspixmapsink_rotate_angle_type;
+}
+
+static GType
+gst_evaspixmapsink_display_geometry_method_get_type(void)
+{
+       static GType evaspixmapsink_display_geometry_method_type = 0;
+       static const GEnumValue display_geometry_method_type[] = {
+               { 0, "Letter box", "LETTER_BOX"},
+               { 1, "Origin size", "ORIGIN_SIZE"},
+               { 2, "Full-screen", "FULL_SCREEN"},
+               { 3, "Cropped Full-screen", "CROPPED_FULL_SCREEN"},
+               { 4, "Explicitely described destination ROI", "CUSTOM_ROI"},
+               { 5, NULL, NULL},
+       };
+
+       if (!evaspixmapsink_display_geometry_method_type) {
+               evaspixmapsink_display_geometry_method_type = g_enum_register_static("GstEvasPixmapSinkDisplayGeometryMethodType", display_geometry_method_type);
+       }
+
+       return evaspixmapsink_display_geometry_method_type;
+}
+
+typedef struct
+{
+  unsigned long flags;
+  unsigned long functions;
+  unsigned long decorations;
+  long input_mode;
+  unsigned long status;
+}
+MotifWmHints, MwmHints;
+
+#define MWM_HINTS_DECORATIONS   (1L << 1)
+
+static void gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink);
+static GstBufferClass *evaspixmap_buffer_parent_class = NULL;
+static void gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf);
+static void gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink);
+static void gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
+static void gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx);
+static gboolean gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf);
+static gboolean gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink);
+static void gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
+static gint gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps);
+static void drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle);
+static void drm_fini_close_gem_handle(GstEvasPixmapSink *evaspixmapsink, Pixmap pixmap_id);
+static void evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void evas_callback_show_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void evas_callback_hide_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+/* Default template - initiated with class struct to allow gst-register to work
+   without X running */
+static GstStaticPadTemplate gst_evaspixmapsink_sink_template_factory =
+    GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/x-raw-rgb, "
+        "framerate = (fraction) [ 0, MAX ], "
+        "width = (int) [ 1, MAX ], "
+        "height = (int) [ 1, MAX ]; "
+        "video/x-raw-yuv, "
+        "framerate = (fraction) [ 0, MAX ], "
+        "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
+    );
+
+enum
+{
+  PROP_0,
+  PROP_CONTRAST,
+  PROP_BRIGHTNESS,
+  PROP_HUE,
+  PROP_SATURATION,
+  PROP_DISPLAY,
+  PROP_SYNCHRONOUS,
+  PROP_PIXEL_ASPECT_RATIO,
+  PROP_DEVICE,
+  PROP_DEVICE_NAME,
+  PROP_DOUBLE_BUFFER,
+  PROP_AUTOPAINT_COLORKEY,
+  PROP_COLORKEY,
+  PROP_PIXMAP_WIDTH,
+  PROP_PIXMAP_HEIGHT,
+  PROP_FLIP,
+  PROP_ROTATE_ANGLE,
+  PROP_DISPLAY_GEOMETRY_METHOD,
+  PROP_ZOOM,
+  PROP_DST_ROI_X,
+  PROP_DST_ROI_Y,
+  PROP_DST_ROI_W,
+  PROP_DST_ROI_H,
+  PROP_STOP_VIDEO,
+  PROP_EVAS_OBJECT,
+  PROP_VISIBLE,
+  PROP_ORIGIN_SIZE,
+};
+
+static GstVideoSinkClass *parent_class = NULL;
+
+/* ============================================================= */
+/*                                                               */
+/*                       Private Methods                         */
+/*                                                               */
+/* ============================================================= */
+
+/* evaspixmap buffers */
+
+#define GST_TYPE_EVASPIXMAP_BUFFER (gst_evaspixmap_buffer_get_type())
+
+#define GST_IS_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EVASPIXMAP_BUFFER))
+#define GST_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_EVASPIXMAP_BUFFER, GstEvasPixmapBuffer))
+
+static int log_warn_count = 0;
+
+Display *g_my_disp;
+
+static int get_millis_time()
+{
+    struct timespec tp;
+    clock_gettime(CLOCK_MONOTONIC, &tp);
+    return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
+}
+
+static void
+ecore_pipe_callback_handler (void *data, void *buffer, unsigned int nbyte)
+{
+       if (!data ) {
+               GST_WARNING ("data is NULL..");
+               return;
+       }
+
+       GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink*)data;
+       GST_DEBUG_OBJECT (evaspixmapsink,"[START] Evas_Object(0x%x)", evaspixmapsink->eo);
+       int i = 0;
+       guint idx = 0;
+       GstXPixmap *xpixmap = NULL;
+
+       g_mutex_lock (evaspixmapsink->flow_lock);
+
+       evaspixmapsink->epipe_request_count--;
+       if (!evaspixmapsink->eo) {
+               GST_WARNING_OBJECT (evaspixmapsink,"evas object is NULL..");
+               g_mutex_unlock (evaspixmapsink->flow_lock);
+               return;
+       }
+
+       if (!evaspixmapsink->xcontext) {
+               GST_WARNING_OBJECT (evaspixmapsink,"xcontext is NULL..");
+               g_mutex_unlock (evaspixmapsink->flow_lock);
+               return;
+       }
+
+       /* setting evas object hide and show */
+       if (nbyte == SIZE_FOR_UPDATE_VISIBILITY) {
+               if(!evaspixmapsink->visible) {
+                       evas_object_hide(evaspixmapsink->eo);
+                       GST_INFO_OBJECT (evaspixmapsink, "object hide");
+               } else {
+                       if (!evas_object_image_native_surface_get(evaspixmapsink->eo)) {
+                               GST_WARNING_OBJECT (evaspixmapsink, "native surface is not set, skip evas_object_show()..");
+                       } else {
+                               evas_object_show(evaspixmapsink->eo);
+                               GST_INFO_OBJECT (evaspixmapsink, "object show");
+                       }
+               }
+               g_mutex_unlock (evaspixmapsink->flow_lock);
+               return;
+       }
+
+       /* mapping evas object with xpixmap */
+       if (evaspixmapsink->do_link) {
+               GST_DEBUG_OBJECT (evaspixmapsink,"do link");
+               evas_object_image_size_set(evaspixmapsink->eo, evaspixmapsink->w, evaspixmapsink->h);
+               if (evaspixmapsink->xpixmap[idx]->pixmap) {
+                       Evas_Native_Surface surf;
+                       surf.version = EVAS_NATIVE_SURFACE_VERSION;
+                       surf.type = EVAS_NATIVE_SURFACE_X11;
+                       surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
+                       surf.data.x11.pixmap = evaspixmapsink->xpixmap[idx]->pixmap;
+                       evas_object_image_native_surface_set(evaspixmapsink->eo, &surf);
+                       evaspixmapsink->do_link = FALSE;
+               } else {
+                       GST_WARNING_OBJECT (evaspixmapsink,"pixmap is NULL..");
+                       g_mutex_unlock (evaspixmapsink->flow_lock);
+                       return;
+               }
+               for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+                       if (evaspixmapsink->xpixmap[i]->prev_pixmap && evaspixmapsink->xpixmap[i]->prev_gc && evaspixmapsink->prev_damage[i]) {
+                               GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d), gc(%x), destroy previous damage(%d)",
+                                               evaspixmapsink->xpixmap[i]->prev_pixmap, evaspixmapsink->xpixmap[i]->prev_gc, evaspixmapsink->prev_damage[i]);
+                               g_mutex_lock (evaspixmapsink->x_lock);
+                               XFreePixmap(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_pixmap);
+                               XFreeGC (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_gc);
+                               XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->prev_damage[i]);
+                               XSync(evaspixmapsink->xcontext->disp, FALSE);
+                               g_mutex_unlock (evaspixmapsink->x_lock);
+                               evaspixmapsink->xpixmap[i]->prev_pixmap = 0;
+                               evaspixmapsink->xpixmap[i]->prev_gc = 0;
+                               evaspixmapsink->prev_damage[i] = NULL;
+                       }
+               }
+               if (evaspixmapsink->visible && !evas_object_visible_get(evaspixmapsink->eo)) {
+                       evas_object_show(evaspixmapsink->eo);
+                       GST_WARNING_OBJECT (evaspixmapsink, "object show (lazy)");
+               }
+
+       } else {
+               GST_DEBUG_OBJECT (evaspixmapsink,"update");
+               /* update evas image object size */
+               if (evaspixmapsink->use_origin_size) {
+                       evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evaspixmapsink->w, &evaspixmapsink->h);
+               }
+
+               g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
+
+               /* find a oldest damaged pixmap */
+               int temp_time = 0;
+               for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+                       if (evaspixmapsink->last_updated_idx == i) {
+                               continue;
+                       } else {
+                               xpixmap = evaspixmapsink->xpixmap[i];
+                               if (xpixmap->ref > 0 && xpixmap->damaged_time) {
+                                       if (temp_time == 0) {
+                                               temp_time = xpixmap->damaged_time;
+                                               idx = i;
+                                       } else {
+                                               if (temp_time > xpixmap->damaged_time) {
+                                                       temp_time = xpixmap->damaged_time;
+                                                       idx = i;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               xpixmap = evaspixmapsink->xpixmap[idx];
+               if (xpixmap->pixmap) {
+                       if (evaspixmapsink->last_updated_idx != idx) {
+                               Evas_Native_Surface surf;
+                               surf.version = EVAS_NATIVE_SURFACE_VERSION;
+                               surf.type = EVAS_NATIVE_SURFACE_X11;
+                               surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
+                               surf.data.x11.pixmap = xpixmap->pixmap;
+                               if (evaspixmapsink->eo) {
+                                       evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
+                               }
+                               evas_object_image_native_surface_set(evaspixmapsink->eo, &surf);
+                               GST_LOG_OBJECT (evaspixmapsink,"update, native_surface_set of xpixmap[%d]",idx);
+                               if (evaspixmapsink->last_updated_idx == -1) {
+                                       xpixmap->damaged_time = 0;
+                                       GST_INFO_OBJECT (evaspixmapsink,"this is the first time to request to update(do not DECREASE ref-count) : pixmap(%d), refcount(%d), damaged_time(%d), idx(%d)",
+                                                                       xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time, idx);
+                               } else {
+                                       xpixmap = evaspixmapsink->xpixmap[evaspixmapsink->last_updated_idx];
+                                       if(xpixmap->ref > 0 && xpixmap->damaged_time > 0) {
+                                               xpixmap->ref--;
+                                               xpixmap->damaged_time = 0;
+                                               GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count DECREASED : pixmap(%d), refcount(%d), damaged_time(%d), idx(%d)",
+                                                                                       xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time, evaspixmapsink->last_updated_idx);
+                                       }
+                               }
+                               evaspixmapsink->last_updated_idx = idx;
+                       }
+
+                       evas_object_image_fill_set(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
+                       evas_object_image_data_update_add(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
+                       //GST_LOG_OBJECT (evaspixmapsink,"request to update : pixmap idx(%d), ref(%d)", idx, xpixmap->ref);
+               } else {
+                       GST_ERROR_OBJECT (evaspixmapsink,"pixmap is NULL..");
+               }
+               g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
+       }
+
+       GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
+       g_mutex_unlock (evaspixmapsink->flow_lock);
+}
+
+static inline gboolean
+is_evas_image_object (Evas_Object *obj)
+{
+       const char *type;
+       if (!obj) {
+               GST_ERROR ("evas image object is NULL..");
+               return FALSE;
+       }
+       type = evas_object_type_get (obj);
+       if (!type) {
+               GST_ERROR ("could not find type of the evas object..");
+               return FALSE;
+       }
+       if (strcmp (type, "image") == 0) {
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static void
+evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+       int w = 0;
+       int h = 0;
+       float former_ratio = 0;
+       float ratio = 0;
+       int i = 0;
+#ifdef COMPARE_RATIO
+       float abs_margin = 0;
+#endif
+
+       GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
+       GST_DEBUG_OBJECT (evaspixmapsink,"[START] evas_image_object(%x), tid(%u)", obj, (unsigned int)pthread_self());
+
+       evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &w, &h);
+       GST_DEBUG_OBJECT (evaspixmapsink,"resized : w(%d), h(%d)", w, h);
+       if (!evaspixmapsink->use_origin_size &&
+                       (evaspixmapsink->w != w || evaspixmapsink->h != h)) {
+               former_ratio = (float)evaspixmapsink->w / evaspixmapsink->h;
+               ratio = (float)w / h;
+               evaspixmapsink->w = w;
+               evaspixmapsink->h = h;
+
+#ifdef COMPARE_RATIO
+               GST_DEBUG_OBJECT (evaspixmapsink,"resized : ratio(%.3f=>%.3f)", former_ratio, ratio);
+               if ( former_ratio >= ratio ) {
+                       abs_margin = former_ratio - ratio;
+               } else {
+                       abs_margin = ratio - former_ratio;
+               }
+               /* re-link_pixmap can only be set when ratio is changed */
+               if ( abs_margin >= MARGIN_OF_ERROR ) {
+#endif
+                       if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
+                               GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
+                               return;
+                       }
+                       for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
+                               if (evaspixmapsink->gem_info[i].ref_pixmap > 0) {
+                                       GST_LOG_OBJECT (evaspixmapsink,"set ref_pixmap(%d) to 0 in gem_info[%d]", evaspixmapsink->gem_info[i].ref_pixmap, i);
+                                       evaspixmapsink->gem_info[i].ref_pixmap = 0;
+                               }
+                       }
+
+                       /**
+                        * Pixmap is reallocated.
+                        * But native surface has old pixmap.
+                        * In this case, evas can rendering with old pixmap.
+                        * That makes broken image in the window.
+                        * So I just unset evas native surface.
+                        */
+                       if (evaspixmapsink->eo) {
+                               evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
+                               evas_object_image_data_set(evaspixmapsink->eo, NULL);
+                       }
+#ifdef COMPARE_RATIO
+               }
+#endif
+       }
+
+       if (GST_STATE(evaspixmapsink) >= GST_STATE_PAUSED) {
+               gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
+       }
+
+       GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
+}
+
+static void
+evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+       GstEvasPixmapSink *evaspixmapsink = data;
+       if (!evaspixmapsink) {
+               GST_WARNING ("evaspixmapsink is NULL..");
+               return;
+       }
+       GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
+
+       EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( evaspixmapsink->eo );
+       if (evaspixmapsink->eo) {
+               evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
+               evaspixmapsink->eo = NULL;
+       }
+
+       GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
+}
+
+static void
+evas_callback_show_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+       GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
+       GST_INFO_OBJECT (evaspixmapsink,"show evas_image_object(%x) from pid(%d), tid(%u)", obj, getpid(), (unsigned int)pthread_self());
+}
+
+static void
+evas_callback_hide_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+       GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
+       GST_INFO_OBJECT (evaspixmapsink,"hide evas_image_object(%x) from pid(%d), tid(%u)", obj, getpid(), (unsigned int)pthread_self());
+}
+
+/* X11 stuff */
+static gboolean error_caught = FALSE;
+
+static int
+gst_evaspixmapsink_handle_xerror (Display * display, XErrorEvent * xevent)
+{
+  char error_msg[1024];
+
+  XGetErrorText (display, xevent->error_code, error_msg, 1024);
+  if (display != g_my_disp) {
+    GST_WARNING ("evaspixmapsink triggered an XError. but display(%p) is not ours(%p), just skip it. error(%s), xevent->request_code(%d)", display, g_my_disp, error_msg, xevent->request_code);
+  } else {
+    GST_ERROR ("evaspixmapsink triggered an XError. error(%s), display(%p), xevent->request_code(%d)", error_msg, display, xevent->request_code);
+    error_caught = TRUE;
+  }
+  return 0;
+}
+
+#ifdef DUMP_IMG
+int util_write_rawdata(const char *file, const void *data, unsigned int size)
+{
+  FILE *fp;
+
+  fp = fopen(file, "wb");
+  if (fp == NULL)
+  {
+    GST_WARNING("fopen fail... size : %d", size);
+    return -1;
+  }
+  fwrite((char*)data, sizeof(char), size, fp);
+  fclose(fp);
+
+  return 0;
+}
+
+void *
+gst_evaspixmapsink_get_buffer (Display *dpy, Pixmap pixmap, int width, int height, int i)
+{
+  if (g_bufinfo[i]!=NULL)
+  {
+    GST_ERROR("g_bufinfo!=NULL %p", g_bufinfo[i]);
+    exit (-1);
+  }
+
+  g_bufinfo[i] = calloc (1, sizeof (BufferInfo));
+
+  g_bufinfo[i]->dpy = dpy;
+  g_bufinfo[i]->pixmap = pixmap;
+  g_bufinfo[i]->width = width;
+  g_bufinfo[i]->height = height;
+
+  if (!gst_evaspixmapsink_init_dri2 (g_bufinfo[i]))
+  {
+    free (g_bufinfo[i]);
+    g_bufinfo[i] = NULL;
+    return NULL;
+  }
+
+  if (g_bufinfo[i]->virtual == NULL)
+  {
+    GST_ERROR("g_bufinfo->virtual == NULL");
+    exit (-1);
+  }
+
+  return g_bufinfo[i]->virtual;
+}
+
+void
+gst_evaspixmapsink_free_buffer (int i)
+{
+  if (g_bufinfo[i] == NULL)
+  {
+    GST_ERROR("g_bufinfo == NULL");
+    exit (-1);
+  }
+
+  if (g_bufinfo[i]==NULL)
+  {
+    GST_ERROR("g_bufinfo==NULL");
+    exit (-1);
+  }
+
+  if (g_bufinfo[i])
+  {
+    if (g_bufinfo[i]->bo)
+      tbm_bo_unref(g_bufinfo[i]->bo);
+    if (g_bufinfo[i]->dri2_buffers)
+      free(g_bufinfo[i]->dri2_buffers);
+    if (g_bufinfo[i]->bufmgr)
+      tbm_bufmgr_deinit (g_bufinfo[i]->bufmgr);
+    if (g_bufinfo[i]->drm_fd >= 0)
+      close (g_bufinfo[i]->drm_fd);
+  }
+
+  XSync (g_bufinfo[i]->dpy, 0);
+  free (g_bufinfo[i]);
+  g_bufinfo[i] = NULL;
+}
+
+static Bool gst_evaspixmapsink_init_dri2 (BufferInfo *bufinfo)
+{
+  int screen;
+  int dri2_base = 0;
+  int dri2_err_base = 0;
+  int dri2Major, dri2Minor;
+  char *driverName = NULL, *deviceName = NULL;
+  unsigned int attachments[1];
+  int dri2_count, dri2_out_count;
+  int dri2_width, dri2_height;
+  drm_magic_t magic;
+  tbm_bo_handle bo_handle;
+  screen = DefaultScreen(bufinfo->dpy);
+  if (!DRI2QueryExtension (bufinfo->dpy, &dri2_base, &dri2_err_base))
+  {
+    GST_ERROR ("no DRI2 extension. !!\n");
+    goto fail_init_dri2;
+  }
+  if (!DRI2QueryVersion (bufinfo->dpy, &dri2Major, &dri2Minor))
+  {
+    GST_ERROR ("fail : DRI2QueryVersion !!\n");
+    goto fail_init_dri2;
+  }
+  if (!DRI2Connect (bufinfo->dpy, RootWindow(bufinfo->dpy, screen), &driverName, &deviceName))
+  {
+    GST_ERROR ("fail : DRI2Connect !!\n");
+    goto fail_init_dri2;
+  }    /* drm_fd */
+  bufinfo->drm_fd = open (deviceName, O_RDWR);
+  if (bufinfo->drm_fd < 0)
+  {
+    GST_ERROR ("fail : open drm device (%s)\n", deviceName);
+    goto fail_init_dri2;
+  }
+  /* get the drm magic */
+  drmGetMagic(bufinfo->drm_fd, &magic);
+  if (!DRI2Authenticate(bufinfo->dpy, RootWindow(bufinfo->dpy, screen), magic))
+  {
+    GST_ERROR ("fail : DRI2Authenticate (%d)\n", magic);
+    goto fail_init_dri2;
+  }
+  /* bufmgr */
+  bufinfo->bufmgr = tbm_bufmgr_init (bufinfo->drm_fd);
+  if (!bufinfo->bufmgr)
+  {
+    GST_ERROR ("fail : init buffer manager \n");
+    goto fail_init_dri2;
+  }
+  DRI2CreateDrawable (bufinfo->dpy, bufinfo->pixmap);
+  attachments[0] = DRI2BufferFrontLeft;
+  dri2_count = 1;
+  bufinfo->dri2_buffers = DRI2GetBuffers (bufinfo->dpy, bufinfo->pixmap, &dri2_width, &dri2_height,
+                                       attachments, dri2_count, &dri2_out_count);
+  if (!bufinfo->dri2_buffers)
+  {
+    GST_ERROR ("fail : get buffers\n");
+    goto fail_init_dri2;
+  }
+  if (!bufinfo->dri2_buffers[0].name)
+  {
+    GST_ERROR ("fail : a handle of the dri2 buffer is null \n ");
+    goto fail_init_dri2;
+  }
+  bufinfo->bo = tbm_bo_import (bufinfo->bufmgr, bufinfo->dri2_buffers[0].name);
+  if (!bufinfo->bo)
+  {
+    GST_ERROR ("fail : import bo (key:%d)\n", bufinfo->dri2_buffers[0].name);
+    goto fail_init_dri2;
+  }
+  /* virtual */
+  bo_handle = tbm_bo_map(bufinfo->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+  if(!bo_handle.ptr)
+  {
+    GST_ERROR ("fail : tbm_bo_map");
+    goto fail_init_dri2;
+  }
+  tbm_bo_unmap (bufinfo->bo);
+
+  bufinfo->virtual = (void *)bo_handle.ptr;
+  if (!bufinfo->virtual)
+  {
+    GST_ERROR ("fail : map \n");
+    goto fail_init_dri2;
+  }
+
+  free (driverName);
+  free (deviceName);
+
+  return True;
+
+  fail_init_dri2:
+  if (driverName)
+    free (driverName);
+  if (deviceName)
+    free (deviceName);
+  if (bufinfo->bo)
+    tbm_bo_unref(bufinfo->bo);
+  if (bufinfo->dri2_buffers)
+    free(bufinfo->dri2_buffers);
+  if (bufinfo->bufmgr)
+    tbm_bufmgr_deinit (bufinfo->bufmgr);
+  if (bufinfo->drm_fd >= 0)
+    close (bufinfo->drm_fd);
+  return False;
+}
+#endif
+
+#ifdef HAVE_XSHM
+/* This function checks that it is actually really possible to create an image
+   using XShm */
+static gboolean
+gst_evaspixmapsink_check_xshm_calls (GstXContext * xcontext)
+{
+  XvImage *xvimage;
+  XShmSegmentInfo SHMInfo;
+  gint size;
+  int (*handler) (Display *, XErrorEvent *);
+  gboolean result = FALSE;
+  gboolean did_attach = FALSE;
+
+  g_return_val_if_fail (xcontext != NULL, FALSE);
+
+  /* Sync to ensure any older errors are already processed */
+  XSync (xcontext->disp, FALSE);
+
+  /* Set defaults so we don't free these later unnecessarily */
+  SHMInfo.shmaddr = ((void *) -1);
+  SHMInfo.shmid = -1;
+
+  /* Setting an error handler to catch failure */
+  error_caught = FALSE;
+  handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
+
+  /* Trying to create a 1x1 picture */
+  GST_DEBUG ("XvShmCreateImage of 1x1");
+  xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
+      xcontext->im_format, NULL, 1, 1, &SHMInfo);
+
+  /* Might cause an error, sync to ensure it is noticed */
+  XSync (xcontext->disp, FALSE);
+  if (!xvimage || error_caught) {
+    GST_WARNING ("could not XvShmCreateImage a 1x1 image");
+    goto beach;
+  }
+  size = xvimage->data_size;
+
+  SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
+  if (SHMInfo.shmid == -1) {
+    GST_WARNING ("could not get shared memory of %d bytes", size);
+    goto beach;
+  }
+
+  SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
+  if (SHMInfo.shmaddr == ((void *) -1)) {
+    GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
+    /* Clean up the shared memory segment */
+    shmctl (SHMInfo.shmid, IPC_RMID, NULL);
+    goto beach;
+  }
+
+  xvimage->data = SHMInfo.shmaddr;
+  SHMInfo.readOnly = FALSE;
+
+  if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
+    GST_WARNING ("Failed to XShmAttach");
+    /* Clean up the shared memory segment */
+    shmctl (SHMInfo.shmid, IPC_RMID, NULL);
+    goto beach;
+  }
+
+  /* Sync to ensure we see any errors we caused */
+  XSync (xcontext->disp, FALSE);
+
+  /* Delete the shared memory segment as soon as everyone is attached.
+   * This way, it will be deleted as soon as we detach later, and not
+   * leaked if we crash. */
+  shmctl (SHMInfo.shmid, IPC_RMID, NULL);
+
+  if (!error_caught) {
+    GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
+        SHMInfo.shmseg);
+
+    did_attach = TRUE;
+    /* store whether we succeeded in result */
+    result = TRUE;
+  } else {
+    GST_WARNING ("MIT-SHM extension check failed at XShmAttach. "
+        "Not using shared memory.");
+  }
+
+beach:
+  /* Sync to ensure we swallow any errors we caused and reset error_caught */
+  XSync (xcontext->disp, FALSE);
+
+  error_caught = FALSE;
+  XSetErrorHandler (handler);
+
+  if (did_attach) {
+    GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
+        SHMInfo.shmid, SHMInfo.shmseg);
+    XShmDetach (xcontext->disp, &SHMInfo);
+    XSync (xcontext->disp, FALSE);
+  }
+  if (SHMInfo.shmaddr != ((void *) -1))
+    shmdt (SHMInfo.shmaddr);
+  if (xvimage)
+    XFree (xvimage);
+  return result;
+}
+#endif /* HAVE_XSHM */
+
+/* This function destroys a GstEvasPixmap handling XShm availability */
+static void
+gst_evaspixmap_buffer_destroy (GstEvasPixmapBuffer *evaspixmapbuf)
+{
+       GstEvasPixmapSink *evaspixmapsink;
+
+       evaspixmapsink = evaspixmapbuf->evaspixmapsink;
+       if (G_UNLIKELY (evaspixmapsink == NULL)) {
+               goto no_sink;
+       }
+       GST_DEBUG_OBJECT (evaspixmapsink, "Destroying buffer");
+
+       g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
+
+       GST_OBJECT_LOCK (evaspixmapsink);
+
+       /* We might have some buffers destroyed after changing state to NULL */
+       if (evaspixmapsink->xcontext == NULL) {
+               GST_DEBUG_OBJECT (evaspixmapsink,"Destroying XvImage after Xcontext");
+#ifdef HAVE_XSHM
+               /* Need to free the shared memory segment even if the x context
+               * was already cleaned up */
+               if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
+                       shmdt (evaspixmapbuf->SHMInfo.shmaddr);
+               }
+#endif
+               goto beach;
+       }
+       g_mutex_lock (evaspixmapsink->x_lock);
+
+#ifdef HAVE_XSHM
+       if (evaspixmapsink->xcontext->use_xshm) {
+               if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
+                       GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmDetaching from 0x%x id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
+                       XShmDetach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo);
+                       XSync (evaspixmapsink->xcontext->disp, FALSE);
+                       shmdt (evaspixmapbuf->SHMInfo.shmaddr);
+               }
+               if (evaspixmapbuf->xvimage)
+               XFree (evaspixmapbuf->xvimage);
+       } else
+#endif /* HAVE_XSHM */
+       {
+               if (evaspixmapbuf->xvimage) {
+                       if (evaspixmapbuf->xvimage->data) {
+                               g_free (evaspixmapbuf->xvimage->data);
+                       }
+                       XFree (evaspixmapbuf->xvimage);
+               }
+       }
+
+       XSync (evaspixmapsink->xcontext->disp, FALSE);
+
+       g_mutex_unlock (evaspixmapsink->x_lock);
+
+beach:
+       GST_OBJECT_UNLOCK (evaspixmapsink);
+       evaspixmapbuf->evaspixmapsink = NULL;
+       gst_object_unref (evaspixmapsink);
+
+       GST_MINI_OBJECT_CLASS (evaspixmap_buffer_parent_class)->finalize (GST_MINI_OBJECT(evaspixmapbuf));
+
+       return;
+
+       no_sink:
+       {
+               GST_WARNING ("no sink found");
+               return;
+       }
+}
+
+static void
+gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf)
+{
+       GstEvasPixmapSink *evaspixmapsink;
+
+       evaspixmapsink = evaspixmapbuf->evaspixmapsink;
+       if (G_UNLIKELY (evaspixmapsink == NULL)) {
+               GST_WARNING_OBJECT (evaspixmapsink,"no sink found");
+               return;
+       }
+       g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
+
+        /* If our geometry changed we can't reuse that image. */
+       GST_LOG_OBJECT (evaspixmapsink,"destroy image as sink is shutting down");
+       gst_evaspixmap_buffer_destroy (evaspixmapbuf);
+}
+
+static void
+gst_evaspixmap_buffer_free (GstEvasPixmapBuffer *evaspixmapbuf)
+{
+  /* make sure it is not recycled */
+  evaspixmapbuf->width = -1;
+  evaspixmapbuf->height = -1;
+  gst_buffer_unref (GST_BUFFER (evaspixmapbuf));
+}
+
+static void
+gst_evaspixmap_buffer_init (GstEvasPixmapBuffer *evaspixmapbuf, gpointer g_class)
+{
+#ifdef HAVE_XSHM
+  evaspixmapbuf->SHMInfo.shmaddr = ((void *) -1);
+  evaspixmapbuf->SHMInfo.shmid = -1;
+#endif
+}
+
+static void
+gst_evaspixmap_buffer_class_init (gpointer g_class, gpointer class_data)
+{
+  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
+
+  evaspixmap_buffer_parent_class = g_type_class_peek_parent (g_class);
+
+  mini_object_class->finalize = (GstMiniObjectFinalizeFunction) gst_evaspixmap_buffer_finalize;
+}
+
+static GType
+gst_evaspixmap_buffer_get_type (void)
+{
+  static GType _gst_evaspixmap_buffer_type;
+
+  if (G_UNLIKELY (_gst_evaspixmap_buffer_type == 0)) {
+    static const GTypeInfo evaspixmap_buffer_info = {
+      sizeof (GstBufferClass),
+      NULL,
+      NULL,
+      gst_evaspixmap_buffer_class_init,
+      NULL,
+      NULL,
+      sizeof (GstEvasPixmapBuffer),
+      0,
+      (GInstanceInitFunc) gst_evaspixmap_buffer_init,
+      NULL
+    };
+    _gst_evaspixmap_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
+        "GstEvasPixmapBuffer", &evaspixmap_buffer_info, 0);
+  }
+  return _gst_evaspixmap_buffer_type;
+}
+
+/* This function handles GstEvasPixmapBuffer creation depending on XShm availability */
+static GstEvasPixmapBuffer*
+gst_evaspixmap_buffer_new (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
+{
+       GstEvasPixmapBuffer *evaspixmapbuf = NULL;
+       GstStructure *structure = NULL;
+       gboolean succeeded = FALSE;
+       int (*handler) (Display *, XErrorEvent *);
+
+       g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
+
+       if (caps == NULL) {
+               return NULL;
+       }
+
+       evaspixmapbuf = (GstEvasPixmapBuffer*) gst_mini_object_new (GST_TYPE_EVASPIXMAP_BUFFER);
+       GST_DEBUG_OBJECT (evaspixmapsink,"Creating new EvasPixmapBuffer");
+
+       structure = gst_caps_get_structure (caps, 0);
+
+       if (!gst_structure_get_int (structure, "width", &evaspixmapbuf->width) || !gst_structure_get_int (structure, "height", &evaspixmapbuf->height)) {
+               GST_WARNING_OBJECT (evaspixmapsink,"failed getting geometry from caps %" GST_PTR_FORMAT, caps);
+       }
+
+       GST_LOG_OBJECT (evaspixmapsink,"creating %dx%d", evaspixmapbuf->width, evaspixmapbuf->height);
+
+       GST_LOG_OBJECT (evaspixmapsink,"aligned size %dx%d", evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
+       if (evaspixmapsink->aligned_width == 0 || evaspixmapsink->aligned_height == 0) {
+               GST_INFO_OBJECT (evaspixmapsink,"aligned size is zero. set size of caps.");
+               evaspixmapsink->aligned_width = evaspixmapbuf->width;
+               evaspixmapsink->aligned_height = evaspixmapbuf->height;
+       }
+
+       evaspixmapbuf->im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
+       if (evaspixmapbuf->im_format == -1) {
+               GST_WARNING_OBJECT (evaspixmapsink,"failed to get format from caps %"GST_PTR_FORMAT, caps);
+               GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",
+                                  evaspixmapbuf->width, evaspixmapbuf->height), ("Invalid input caps"));
+               goto beach_unlocked;
+       }
+
+       GST_INFO_OBJECT (evaspixmapsink, "FOURCC format : %c%c%c%c", evaspixmapbuf->im_format, evaspixmapbuf->im_format>>8,
+                       evaspixmapbuf->im_format>>16, evaspixmapbuf->im_format>>24);
+
+       evaspixmapbuf->evaspixmapsink = gst_object_ref (evaspixmapsink);
+
+       g_mutex_lock (evaspixmapsink->x_lock);
+
+       /* Sync to ensure we swallow any errors we caused and reset error_caught */
+       XSync (evaspixmapsink->xcontext->disp, FALSE);
+
+       /* Setting an error handler to catch failure */
+       error_caught = FALSE;
+       handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
+
+#ifdef HAVE_XSHM
+       if (evaspixmapsink->xcontext->use_xshm) {
+               int expected_size;
+               evaspixmapbuf->xvimage = XvShmCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, evaspixmapbuf->im_format, NULL,
+               evaspixmapsink->aligned_width, evaspixmapsink->aligned_height, &evaspixmapbuf->SHMInfo);
+               if (!evaspixmapbuf->xvimage || error_caught) {
+                       if (error_caught) {
+                               GST_ERROR_OBJECT (evaspixmapsink,"error_caught!");
+                       }
+                       if(!evaspixmapbuf->xvimage) {
+                               GST_ERROR_OBJECT (evaspixmapsink,"XvShmCreateImage() failed");
+                       }
+                       g_mutex_unlock (evaspixmapsink->x_lock);
+                       /* Reset error handler */
+                       error_caught = FALSE;
+                       XSetErrorHandler (handler);
+                       /* Push an error */
+                       GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",evaspixmapbuf->width,
+                                  evaspixmapbuf->height),("could not XvShmCreateImage a %dx%d image",evaspixmapbuf->width, evaspixmapbuf->height));
+                       goto beach_unlocked;
+               }
+
+               /* we have to use the returned data_size for our shm size */
+               evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
+               GST_LOG_OBJECT (evaspixmapsink,"XShm image size is %" G_GSIZE_FORMAT, evaspixmapbuf->size);
+
+               /* calculate the expected size.  This is only for sanity checking the
+               * number we get from X. */
+               switch (evaspixmapbuf->im_format) {
+               case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+               case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
+               {
+                       gint pitches[3];
+                       gint offsets[3];
+                       guint plane;
+
+                       offsets[0] = 0;
+                       pitches[0] = GST_ROUND_UP_4 (evaspixmapbuf->width);
+                       offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (evaspixmapbuf->height);
+                       pitches[1] = GST_ROUND_UP_8 (evaspixmapbuf->width) / 2;
+                       offsets[2] =
+                       offsets[1] + pitches[1] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
+                       pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
+
+                       expected_size = offsets[2] + pitches[2] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
+
+                       for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
+                               GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a expected pitch of %d bytes, " "offset of %d",
+                                               plane, pitches[plane], offsets[plane]);
+                       }
+                       break;
+               }
+               case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
+               case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+                       expected_size = evaspixmapbuf->height * GST_ROUND_UP_4 (evaspixmapbuf->width * 2);
+                       break;
+               case GST_MAKE_FOURCC ('S', 'T', '1', '2'):
+               case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
+               case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
+               case GST_MAKE_FOURCC ('S', 'U', 'Y', '2'):
+               case GST_MAKE_FOURCC ('S', '4', '2', '0'):
+               case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
+               case GST_MAKE_FOURCC ('I', 'T', 'L', 'V'):
+               case GST_MAKE_FOURCC ('S', 'R', '3', '2'):
+                       expected_size = sizeof(SCMN_IMGB);
+                       break;
+               default:
+                       expected_size = 0;
+                       break;
+               }
+               if (expected_size != 0 && evaspixmapbuf->size != expected_size) {
+                       GST_WARNING_OBJECT (evaspixmapsink,"unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)", evaspixmapbuf->size, expected_size);
+               }
+
+               /* Be verbose about our XvImage stride */
+               {
+                       guint plane;
+                       for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
+                               GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a pitch of %d bytes, ""offset of %d", plane,
+                                               evaspixmapbuf->xvimage->pitches[plane], evaspixmapbuf->xvimage->offsets[plane]);
+                       }
+               }
+
+               evaspixmapbuf->SHMInfo.shmid = shmget (IPC_PRIVATE, evaspixmapbuf->size,IPC_CREAT | 0777);
+               if (evaspixmapbuf->SHMInfo.shmid == -1) {
+                       g_mutex_unlock (evaspixmapsink->x_lock);
+                       GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
+                               ("Failed to create output image buffer of %dx%d pixels", evaspixmapbuf->width, evaspixmapbuf->height),
+                               ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",evaspixmapbuf->size));
+                       goto beach_unlocked;
+               }
+
+               evaspixmapbuf->SHMInfo.shmaddr = shmat (evaspixmapbuf->SHMInfo.shmid, NULL, 0);
+               if (evaspixmapbuf->SHMInfo.shmaddr == ((void *) -1)) {
+                       g_mutex_unlock (evaspixmapsink->x_lock);
+                       GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
+                               ("Failed to create output image buffer of %dx%d pixels",
+                               evaspixmapbuf->width, evaspixmapbuf->height),
+                               ("Failed to shmat: %s", g_strerror (errno)));
+                       /* Clean up the shared memory segment */
+                       shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
+                       goto beach_unlocked;
+               }
+
+               evaspixmapbuf->xvimage->data = evaspixmapbuf->SHMInfo.shmaddr;
+               evaspixmapbuf->SHMInfo.readOnly = FALSE;
+
+               if (XShmAttach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo) == 0) {
+               /* Clean up the shared memory segment */
+               shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
+
+               g_mutex_unlock (evaspixmapsink->x_lock);
+               GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
+                       ("Failed to create output image buffer of %dx%d pixels",
+                       evaspixmapbuf->width, evaspixmapbuf->height), ("Failed to XShmAttach"));
+               goto beach_unlocked;
+               }
+
+               XSync (evaspixmapsink->xcontext->disp, FALSE);
+
+               /* Delete the shared memory segment as soon as we everyone is attached.
+               * This way, it will be deleted as soon as we detach later, and not
+               * leaked if we crash. */
+               shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
+
+               GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmAttached to 0x%x, id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
+       } else
+#endif /* HAVE_XSHM */
+       {
+               evaspixmapbuf->xvimage = XvCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id,
+               evaspixmapbuf->im_format, NULL, evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
+               if (!evaspixmapbuf->xvimage || error_caught) {
+                       g_mutex_unlock (evaspixmapsink->x_lock);
+                       /* Reset error handler */
+                       error_caught = FALSE;
+                       XSetErrorHandler (handler);
+                       /* Push an error */
+                       GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
+                               ("Failed to create outputimage buffer of %dx%d pixels",
+                               evaspixmapbuf->width, evaspixmapbuf->height),
+                               ("could not XvCreateImage a %dx%d image",
+                               evaspixmapbuf->width, evaspixmapbuf->height));
+                       goto beach_unlocked;
+               }
+
+               /* we have to use the returned data_size for our image size */
+               evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
+               evaspixmapbuf->xvimage->data = g_malloc (evaspixmapbuf->size);
+
+               XSync (evaspixmapsink->xcontext->disp, FALSE);
+       }
+
+       /* Reset error handler */
+       error_caught = FALSE;
+       XSetErrorHandler (handler);
+
+       succeeded = TRUE;
+
+       GST_BUFFER_DATA (evaspixmapbuf) = (guchar *) evaspixmapbuf->xvimage->data;
+       GST_BUFFER_SIZE (evaspixmapbuf) = evaspixmapbuf->size;
+
+       g_mutex_unlock (evaspixmapsink->x_lock);
+
+beach_unlocked:
+       if (!succeeded) {
+               gst_evaspixmap_buffer_free (evaspixmapbuf);
+               evaspixmapbuf = NULL;
+       }
+
+       return evaspixmapbuf;
+}
+
+/* This function puts a GstEvasPixmapBuffer on a GstEvasPixmapSink's pixmap. Returns FALSE
+ * if no pixmap was available  */
+static gboolean
+gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf)
+{
+       GstVideoRectangle result;
+
+       GstVideoRectangle src_origin = { 0, 0, 0, 0};
+       GstVideoRectangle src_input  = { 0, 0, 0, 0};
+       GstVideoRectangle src = { 0, 0, 0, 0};
+       GstVideoRectangle dst = { 0, 0, 0, 0};
+       int rotate = 0;
+       int ret = 0;
+       int idx = 0;
+       GstXPixmap *xpixmap = NULL;
+       int i = 0;
+
+       /* We take the flow_lock. If expose is in there we don't want to run
+       concurrently from the data flow thread */
+       g_mutex_lock (evaspixmapsink->flow_lock);
+
+       if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
+               GST_WARNING_OBJECT (evaspixmapsink, "xpixmap is NULL. Skip buffer_put." );
+               g_mutex_unlock(evaspixmapsink->flow_lock);
+               return TRUE;
+       }
+       if (evaspixmapsink->visible == FALSE) {
+               GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. Skip buffer_put." );
+               g_mutex_unlock(evaspixmapsink->flow_lock);
+               return TRUE;
+       }
+       if (!evaspixmapbuf) {
+               GST_WARNING_OBJECT (evaspixmapsink, "evaspixmapbuf is NULL. Skip buffer_put." );
+               g_mutex_unlock(evaspixmapsink->flow_lock);
+               return TRUE;
+       }
+
+       g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
+       if (evaspixmapsink->last_updated_idx == -1) {
+               /* if it has never been updated any frame in Ecore thread, do below */
+               idx = 0;
+               xpixmap = evaspixmapsink->xpixmap[idx];
+               xpixmap->ref = 1;
+               GST_LOG_OBJECT (evaspixmapsink, "last_updated_idx(%d), we use index[%d] of pixmap buffers : pixmap(%d), ref(%d)",
+                               evaspixmapsink->last_updated_idx, idx, xpixmap->pixmap, xpixmap->ref);
+       } else {
+               for (idx = 0; idx < evaspixmapsink->num_of_pixmaps; idx++) {
+                       if (idx == evaspixmapsink->last_updated_idx) {
+                               continue;
+                       } else {
+                               xpixmap = evaspixmapsink->xpixmap[idx];
+                               if (xpixmap->ref == 0 && xpixmap->damaged_time == 0) {
+                                       xpixmap->ref++;
+                                       GST_LOG_OBJECT (evaspixmapsink, "found an available pixmap(%d) : xpixmap[%d]", xpixmap->pixmap, idx);
+                                       GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count INCREASED : pixmap(%d), refcount(%d)", xpixmap->pixmap, xpixmap->ref);
+                                       break;
+                               }
+                       }
+               }
+               if (idx == evaspixmapsink->num_of_pixmaps) {
+                       GST_LOG_OBJECT (evaspixmapsink, "Could not find a pixmap with idle state, skip buffer_put." );
+                       g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
+                       g_mutex_unlock(evaspixmapsink->flow_lock);
+                       return TRUE;
+               }
+       }
+       g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
+
+       gst_evaspixmapsink_xpixmap_update_geometry(evaspixmapsink, idx);
+
+       src.x = src.y = 0;
+       src_origin.x = src_origin.y = src_input.x = src_input.y = 0;
+       src_input.w = src_origin.w = evaspixmapsink->video_width;
+       src_input.h = src_origin.h = evaspixmapsink->video_height;
+       if (evaspixmapsink->use_origin_size ||
+               (evaspixmapsink->rotate_angle == DEGREE_0 ||
+               evaspixmapsink->rotate_angle == DEGREE_180)) {
+               src.w = src_origin.w;
+               src.h = src_origin.h;
+       } else {
+               src.w = src_origin.h;
+               src.h = src_origin.w;
+       }
+
+       dst.w = evaspixmapsink->render_rect.w; /* pixmap width */
+       dst.h = evaspixmapsink->render_rect.h; /* pixmap height */
+
+       if (!evaspixmapsink->use_origin_size) {
+               static Atom atom_rotation = None;
+               static Atom atom_hflip = None;
+               static Atom atom_vflip = None;
+               gboolean set_hflip = FALSE;
+               gboolean set_vflip = FALSE;
+
+               /* compensation of size information (between evas image object's and pixmap's) */
+               if (evaspixmapsink->sizediff_width > 1) {
+                       if (evaspixmapsink->sizediff_height > 1) {
+                               dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
+                               dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
+                       } else {
+                               dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
+                       }
+               } else if (evaspixmapsink->sizediff_height > 1) {
+                       dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
+               }
+
+               switch (evaspixmapsink->display_geometry_method) {
+               case DISP_GEO_METHOD_LETTER_BOX:
+                       gst_video_sink_center_rect (src, dst, &result, TRUE);
+                       result.x += evaspixmapsink->render_rect.x;
+                       result.y += evaspixmapsink->render_rect.y;
+                       GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : letter box");
+                       break;
+               case DISP_GEO_METHOD_ORIGIN_SIZE:
+                       gst_video_sink_center_rect (src, dst, &result, FALSE);
+                       gst_video_sink_center_rect (dst, src, &src_input, FALSE);
+                       GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : origin size");
+                       if (evaspixmapsink->rotate_angle == DEGREE_90 ||
+                               evaspixmapsink->rotate_angle == DEGREE_270) {
+                               src_input.x = src_input.x ^ src_input.y;
+                               src_input.y = src_input.x ^ src_input.y;
+                               src_input.x = src_input.x ^ src_input.y;
+                               src_input.w = src_input.w ^ src_input.h;
+                               src_input.h = src_input.w ^ src_input.h;
+                               src_input.w = src_input.w ^ src_input.h;
+                       }
+                       break;
+               case DISP_GEO_METHOD_FULL_SCREEN:
+                       result.x = result.y = 0;
+                       result.w = evaspixmapsink->xpixmap[idx]->width;
+                       result.h = evaspixmapsink->xpixmap[idx]->height;
+                       GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : full screen");
+                       break;
+               case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
+                       GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : cropped full screen");
+                       gst_video_sink_center_rect(dst, src, &src_input, TRUE);
+                       result.x = result.y = 0;
+                       result.w = dst.w;
+                       result.h = dst.h;
+                       if (evaspixmapsink->rotate_angle == DEGREE_90 ||
+                               evaspixmapsink->rotate_angle == DEGREE_270) {
+                               src_input.x = src_input.x ^ src_input.y;
+                               src_input.y = src_input.x ^ src_input.y;
+                               src_input.x = src_input.x ^ src_input.y;
+                               src_input.w = src_input.w ^ src_input.h;
+                               src_input.h = src_input.w ^ src_input.h;
+                               src_input.w = src_input.w ^ src_input.h;
+                       }
+                       break;
+               case DISP_GEO_METHOD_CUSTOM_ROI:
+                       switch (evaspixmapsink->rotate_angle) {
+                       case DEGREE_90:
+                               result.w = evaspixmapsink->dst_roi.h;
+                               result.h = evaspixmapsink->dst_roi.w;
+                               result.x = evaspixmapsink->dst_roi.y;
+                               result.y = evaspixmapsink->xpixmap[idx]->height - evaspixmapsink->dst_roi.x - evaspixmapsink->dst_roi.w;
+                               break;
+                       case DEGREE_180:
+                               result.w = evaspixmapsink->dst_roi.w;
+                               result.h = evaspixmapsink->dst_roi.h;
+                               result.x = evaspixmapsink->xpixmap[idx]->width - result.w - evaspixmapsink->dst_roi.x;
+                               result.y = evaspixmapsink->xpixmap[idx]->height - result.h - evaspixmapsink->dst_roi.y;
+                               break;
+                       case DEGREE_270:
+                               result.w = evaspixmapsink->dst_roi.h;
+                               result.h = evaspixmapsink->dst_roi.w;
+                               result.x = evaspixmapsink->xpixmap[idx]->width - evaspixmapsink->dst_roi.y - evaspixmapsink->dst_roi.h;
+                               result.y = evaspixmapsink->dst_roi.x;
+                               break;
+                       default:
+                               result.x = evaspixmapsink->dst_roi.x;
+                               result.y = evaspixmapsink->dst_roi.y;
+                               result.w = evaspixmapsink->dst_roi.w;
+                               result.h = evaspixmapsink->dst_roi.h;
+                               break;
+                       }
+                       GST_LOG_OBJECT(evaspixmapsink, "rotate[%d], ROI input[%d,%d,%dx%d] > result[%d,%d,%dx%d]",
+                                       evaspixmapsink->rotate_angle,
+                                       evaspixmapsink->dst_roi.x, evaspixmapsink->dst_roi.y, evaspixmapsink->dst_roi.w, evaspixmapsink->dst_roi.h,
+                                       result.x, result.y, result.w, result.h);
+                       break;
+               default:
+                       break;
+               }
+               GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : src(%dx%d), dst(%dx%d), result(%dx%d), result_x(%d), result_y(%d)",
+                               src.w,src.h,dst.w,dst.h,result.w,result.h,result.x,result.y);
+
+               switch( evaspixmapsink->rotate_angle ) {
+                       case DEGREE_0:
+                       break;
+                       case DEGREE_90:
+                       rotate = 270;
+                       break;
+                       case DEGREE_180:
+                       rotate = 180;
+                       break;
+                       case DEGREE_270:
+                       rotate = 90;
+                       break;
+                       default:
+                       GST_WARNING_OBJECT( evaspixmapsink, "Unsupported rotation [%d]... set DEGREE 0.",
+                                       evaspixmapsink->rotate_angle );
+                       break;
+               }
+
+               g_mutex_lock (evaspixmapsink->x_lock);
+
+               /* set display rotation */
+               if (atom_rotation == None) {
+                       atom_rotation = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_ROTATION", False);
+               }
+               ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate);
+               if (ret != Success) {
+                       GST_ERROR_OBJECT( evaspixmapsink, "XvSetPortAttribute failed[%d]. disp[%x],xv_port_id[%d],atom[%x],rotate[%d]",
+                                       ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate );
+               }
+
+               /* set display flip */
+               if (atom_hflip == None) {
+                       atom_hflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_HFLIP", False);
+               }
+               if (atom_vflip == None) {
+                       atom_vflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_VFLIP", False);
+               }
+
+               switch (evaspixmapsink->flip) {
+               case FLIP_HORIZONTAL:
+                       set_hflip = TRUE;
+                       set_vflip = FALSE;
+                       break;
+               case FLIP_VERTICAL:
+                       set_hflip = FALSE;
+                       set_vflip = TRUE;
+                       break;
+               case FLIP_BOTH:
+                       set_hflip = TRUE;
+                       set_vflip = TRUE;
+                       break;
+               case FLIP_NONE:
+               default:
+                       set_hflip = FALSE;
+                       set_vflip = FALSE;
+                       break;
+               }
+               GST_INFO_OBJECT(evaspixmapsink, "set rotate %d HFLIP %d, VFLIP %d", rotate, set_hflip, set_vflip);
+
+               ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
+               if (ret != Success) {
+                       GST_WARNING("set HFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],hflip[%d]",
+                                       ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
+               }
+               ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
+               if (ret != Success) {
+                       GST_WARNING("set VFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],vflip[%d]",
+                                       ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
+               }
+
+               g_mutex_unlock (evaspixmapsink->x_lock);
+
+       } else {
+               result.x = result.y = 0;
+               result.w = evaspixmapsink->xpixmap[idx]->width;
+               result.h = evaspixmapsink->xpixmap[idx]->height;
+               GST_INFO_OBJECT (evaspixmapsink, "USE ORIGIN SIZE, no geometry method, no rotation/flip" );
+       }
+
+       if((evaspixmapsink->result_prev.w != 0 && evaspixmapsink->result_prev.h != 0)
+               && (evaspixmapsink->src_prev.w==src_origin.w && evaspixmapsink->src_prev.h==src_origin.h)
+               && (evaspixmapsink->result_prev.w!=result.w || evaspixmapsink->result_prev.h!=result.h))
+       {
+               GST_WARNING("It will execute XFillRectangle..... evaspixmapsink->result_prev.w : %d, evaspixmapsink->result_prev.h: %d, result.w : %d, result.h : %d",
+                       evaspixmapsink->result_prev.w, evaspixmapsink->result_prev.h, result.w, result.h);
+               for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+                       XFillRectangle (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc,
+                               0, 0, evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
+                       GST_LOG_OBJECT (evaspixmapsink,"fill black to xpixmap[%d] with size(w:%d,h:%d)", evaspixmapsink->xpixmap[i]->pixmap,
+                               evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
+               }
+       }
+       g_mutex_lock (evaspixmapsink->x_lock);
+
+  /* We scale to the pixmap's geometry */
+#ifdef HAVE_XSHM
+       if (evaspixmapsink->xcontext->use_xshm) {
+               GST_LOG_OBJECT (evaspixmapsink,"XvShmPutImage with image %dx%d and pixmap %dx%d, from xvimage %"
+                               GST_PTR_FORMAT,
+                               evaspixmapbuf->width, evaspixmapbuf->height,
+                               evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h, evaspixmapbuf);
+
+       /* Trim as proper size */
+       if (src_input.w % 2 == 1) {
+               src_input.w += 1;
+       }
+       if (src_input.h % 2 == 1) {
+               src_input.h += 1;
+       }
+
+       GST_LOG_OBJECT (evaspixmapsink, "screen[%dx%d],pixmap[%d,%d,%dx%d],method[%d],rotate[%d],src[%dx%d],dst[%d,%d,%dx%d],input[%d,%d,%dx%d],result[%d,%d,%dx%d]",
+               evaspixmapsink->scr_w, evaspixmapsink->scr_h,
+               evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y, evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
+               evaspixmapsink->display_geometry_method, rotate,
+               src_origin.w, src_origin.h,
+               dst.x, dst.y, dst.w, dst.h,
+               src_input.x, src_input.y, src_input.w, src_input.h,
+               result.x, result.y, result.w, result.h );
+
+       if (evaspixmapsink->visible) {
+               if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
+                       EVASPIXMAPSINK_SET_PIXMAP_ID_TO_GEM_INFO (evaspixmapsink, evaspixmapsink->xpixmap[idx]->pixmap);
+               }
+               ret = XvShmPutImage (evaspixmapsink->xcontext->disp,
+                       evaspixmapsink->xcontext->xv_port_id,
+                       evaspixmapsink->xpixmap[idx]->pixmap,
+                       evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
+                       src_input.x, src_input.y, src_input.w, src_input.h,
+                       result.x, result.y, result.w, result.h, FALSE);
+               GST_LOG_OBJECT (evaspixmapsink, "XvShmPutImage return value [%d]", ret );
+       } else {
+               GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
+       }
+  } else
+#endif /* HAVE_XSHM */
+       {
+               if (evaspixmapsink->visible) {
+                       XvPutImage (evaspixmapsink->xcontext->disp,
+                                       evaspixmapsink->xcontext->xv_port_id,
+                                       evaspixmapsink->xpixmap[idx]->pixmap,
+                                       evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
+                                       evaspixmapsink->disp_x, evaspixmapsink->disp_y,
+                                       evaspixmapsink->disp_width, evaspixmapsink->disp_height,
+                                       result.x, result.y, result.w, result.h);
+               } else {
+                       GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
+               }
+       }
+
+       evaspixmapsink->src_prev.w = src_origin.w;
+       evaspixmapsink->src_prev.h = src_origin.h;
+
+       evaspixmapsink->result_prev.w = result.w;
+       evaspixmapsink->result_prev.h = result.h;
+
+       XSync (evaspixmapsink->xcontext->disp, FALSE);
+
+       g_mutex_unlock (evaspixmapsink->x_lock);
+       g_mutex_unlock (evaspixmapsink->flow_lock);
+
+       return TRUE;
+}
+
+static int
+drm_init(GstEvasPixmapSink *evaspixmapsink)
+{
+       Display *dpy;
+       int i = 0;
+       int eventBase = 0;
+       int errorBase = 0;
+       int dri2Major = 0;
+       int dri2Minor = 0;
+       char *driverName = NULL;
+       char *deviceName = NULL;
+       struct drm_auth auth_arg = {0};
+
+       evaspixmapsink->drm_fd = -1;
+
+       dpy = XOpenDisplay(0);
+
+       /* DRI2 */
+       if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
+               GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryExtension()");
+               goto ERROR_CASE;
+       }
+
+       if (!DRI2QueryVersion(dpy, &dri2Major, &dri2Minor)) {
+               GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryVersion");
+               goto ERROR_CASE;
+       }
+
+       if (!DRI2Connect(dpy, RootWindow(dpy, DefaultScreen(dpy)), &driverName, &deviceName)) {
+               GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2Connect");
+               goto ERROR_CASE;
+       }
+
+       if (!driverName || !deviceName) {
+               GST_ERROR_OBJECT (evaspixmapsink,"driverName or deviceName is not valid");
+               goto ERROR_CASE;
+       }
+
+       GST_INFO_OBJECT (evaspixmapsink,"Open drm device : %s", deviceName);
+
+       /* get the drm_fd though opening the deviceName */
+       evaspixmapsink->drm_fd = open(deviceName, O_RDWR);
+       if (evaspixmapsink->drm_fd < 0) {
+               GST_ERROR_OBJECT (evaspixmapsink,"cannot open drm device (%s)", deviceName);
+               goto ERROR_CASE;
+       }
+
+       /* get magic from drm to authentication */
+       if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GET_MAGIC, &auth_arg)) {
+               GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm auth magic");
+               close(evaspixmapsink->drm_fd);
+               evaspixmapsink->drm_fd = -1;
+               goto ERROR_CASE;
+       }
+
+       if (!DRI2Authenticate(dpy, RootWindow(dpy, DefaultScreen(dpy)), auth_arg.magic)) {
+               GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm authentication from X");
+               close(evaspixmapsink->drm_fd);
+               evaspixmapsink->drm_fd = -1;
+               goto ERROR_CASE;
+       }
+
+       /* init gem handle */
+       for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
+               evaspixmapsink->gem_info[i].dmabuf_fd = 0;
+               evaspixmapsink->gem_info[i].gem_handle = 0;
+               evaspixmapsink->gem_info[i].gem_name = 0;
+               evaspixmapsink->gem_info[i].bo = 0;
+               evaspixmapsink->gem_info[i].ref_pixmap = 0;
+       }
+
+       XCloseDisplay(dpy);
+       free(driverName);
+       free(deviceName);
+
+       return 0;
+
+ERROR_CASE:
+       XCloseDisplay(dpy);
+       if (driverName) {
+               free(driverName);
+       }
+       if (deviceName) {
+               free(deviceName);
+       }
+
+       return -1;
+}
+
+static void
+drm_fini(GstEvasPixmapSink *evaspixmapsink)
+{
+       if (evaspixmapsink->drm_fd >= 0) {
+               GST_INFO_OBJECT (evaspixmapsink,"close drm_fd(%d)", evaspixmapsink->drm_fd);
+               close(evaspixmapsink->drm_fd);
+               evaspixmapsink->drm_fd = -1;
+       }
+}
+
+static unsigned int
+drm_init_convert_dmabuf_gemname(GstEvasPixmapSink *evaspixmapsink, int dmabuf_fd)
+{
+       struct drm_prime_handle prime_arg = {0,};
+       struct drm_gem_flink flink_arg = {0,};
+       int i = 0;
+
+       if (evaspixmapsink->drm_fd < 0) {
+               GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
+               return 0;
+       }
+
+       if (dmabuf_fd <= 0) {
+               GST_DEBUG_OBJECT (evaspixmapsink,"Ignore wrong dmabuf fd(%d)", dmabuf_fd);              /* temporarily change log level to DEBUG for reducing WARNING level log */
+               return 0;
+       }
+
+       /* check duplicated dmabuf fd */
+       for (i = 0 ; i < MAX_GEM_BUFFER_NUM ; i++) {
+               if (evaspixmapsink->gem_info[i].dmabuf_fd == dmabuf_fd) {
+                       GST_LOG_OBJECT (evaspixmapsink,"already got fd(%u) with name(%u)", dmabuf_fd, evaspixmapsink->gem_info[i].gem_name);
+                       return evaspixmapsink->gem_info[i].gem_name;
+               }
+
+               if (evaspixmapsink->gem_info[i].dmabuf_fd == 0) {
+                       GST_LOG_OBJECT (evaspixmapsink,"empty gem_info[%d] found", i);
+                       break;
+               }
+       }
+
+       if (i == MAX_GEM_BUFFER_NUM) {
+               GST_WARNING_OBJECT (evaspixmapsink,"too many buffers[dmabuf_fd(%d). skip it]", dmabuf_fd);
+               return 0;
+       }
+
+       evaspixmapsink->gem_info[i].dmabuf_fd = dmabuf_fd;
+       prime_arg.fd = dmabuf_fd;
+       if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_arg)) {
+               GST_ERROR_OBJECT (evaspixmapsink,"non dmabuf fd(%d)", dmabuf_fd);
+               return 0;
+       }
+
+       evaspixmapsink->gem_info[i].gem_handle = prime_arg.handle;
+       GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_handle = %u", i, prime_arg.handle);
+
+       flink_arg.handle = prime_arg.handle;
+       if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_FLINK, &flink_arg)) {
+               GST_ERROR_OBJECT (evaspixmapsink,"cannot convert drm handle to name");
+               return 0;
+       }
+
+       evaspixmapsink->gem_info[i].gem_name = flink_arg.name;
+       GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_name = %u", i, flink_arg.name);
+
+       return flink_arg.name;
+}
+
+static unsigned int
+tbm_init_convert_bo_gemname(GstEvasPixmapSink *evaspixmapsink, tbm_bo bo)
+{
+       int i = 0;
+
+       if (bo == NULL) {
+               GST_DEBUG_OBJECT (evaspixmapsink,"Ignore wrong bo(%u)", bo);            /* temporarily change log level to DEBUG for reducing WARNING level log */
+               return 0;
+       }
+
+       /* check duplicated dmabuf bo */
+       for (i = 0 ; i < MAX_GEM_BUFFER_NUM ; i++) {
+               if (evaspixmapsink->gem_info[i].bo == bo) {
+                       GST_LOG_OBJECT (evaspixmapsink,"already got bo(%u) with name(%u)", bo, evaspixmapsink->gem_info[i].gem_name);
+                       return evaspixmapsink->gem_info[i].gem_name;
+               }
+
+               if (evaspixmapsink->gem_info[i].bo == 0) {
+                       GST_LOG_OBJECT (evaspixmapsink,"empty gem_info[%d] found", i);
+                       break;
+               }
+       }
+
+       if (i == MAX_GEM_BUFFER_NUM) {
+               GST_WARNING_OBJECT (evaspixmapsink,"too many buffers[dmabuf_bo(%d). skip it]", bo);
+               return 0;
+       }
+
+       evaspixmapsink->gem_info[i].bo = bo;
+       evaspixmapsink->gem_info[i].gem_name = tbm_bo_export(bo);
+       GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_name = %u", i, evaspixmapsink->gem_info[i].gem_name);
+
+       return evaspixmapsink->gem_info[i].gem_name;
+}
+
+static void
+drm_fini_close_gem_handle(GstEvasPixmapSink *evaspixmapsink, Pixmap pixmap_id)
+{
+       int i = 0;
+       if (evaspixmapsink->drm_fd >= 0) {
+               if (pixmap_id == 0) {
+                       for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
+                               if (evaspixmapsink->gem_info[i].dmabuf_fd > 0 || evaspixmapsink->gem_info[i].bo > 0) {
+                                       if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
+                                               GST_INFO_OBJECT (evaspixmapsink,"close gem_handle(%u)", evaspixmapsink->gem_info[i].gem_handle);
+                                               drm_close_gem(evaspixmapsink, evaspixmapsink->gem_info[i].gem_handle);
+                                       }
+                                       evaspixmapsink->gem_info[i].dmabuf_fd = 0;
+                                       evaspixmapsink->gem_info[i].gem_handle = 0;
+                                       evaspixmapsink->gem_info[i].gem_name = 0;
+                                       evaspixmapsink->gem_info[i].bo = 0;
+                                       evaspixmapsink->gem_info[i].ref_pixmap = 0;
+                                       GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d] is cleared",i);
+                               }
+                       }
+               } else {
+                       for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
+                               if (evaspixmapsink->gem_info[i].ref_pixmap == pixmap_id) {
+                                       if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
+                                               GST_INFO_OBJECT (evaspixmapsink,"close gem_handle(%u) for pixmap_id(%d)",
+                                                                               evaspixmapsink->gem_info[i].gem_handle, pixmap_id);
+                                               drm_close_gem(evaspixmapsink, evaspixmapsink->gem_info[i].gem_handle);
+                                       }
+                                       evaspixmapsink->gem_info[i].dmabuf_fd = 0;
+                                       evaspixmapsink->gem_info[i].gem_handle = 0;
+                                       evaspixmapsink->gem_info[i].gem_name = 0;
+                                       evaspixmapsink->gem_info[i].bo = 0;
+                                       evaspixmapsink->gem_info[i].ref_pixmap = 0;
+                                       GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d] is cleared",i);
+                                       break;
+                               }
+                       }
+               }
+       }
+}
+
+static void
+drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle)
+{
+       struct drm_gem_close close_arg = {0,};
+
+       if (evaspixmapsink->drm_fd < 0) {
+               GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
+               return;
+       }
+
+       if (gem_handle == 0) {
+               GST_ERROR_OBJECT (evaspixmapsink,"invalid gem_handle(%d)",gem_handle);
+               return;
+       }
+
+       close_arg.handle = gem_handle;
+       if (gem_handle > 0 && ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_CLOSE, &close_arg)) {
+               GST_ERROR_OBJECT (evaspixmapsink,"cannot close drm gem handle(%d)", gem_handle);
+               return;
+       }
+
+       return;
+}
+
+/* This function destroys a GstXPixmap */
+static void
+gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
+{
+       g_return_if_fail (xpixmap != NULL);
+       g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
+
+       g_mutex_lock (evaspixmapsink->x_lock);
+
+       if(xpixmap->pixmap) {
+               GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d)", xpixmap->pixmap);
+               XFreePixmap(evaspixmapsink->xcontext->disp, xpixmap->pixmap);
+               xpixmap->pixmap = 0;
+       }
+
+       if (xpixmap->gc) {
+               XFreeGC (evaspixmapsink->xcontext->disp, xpixmap->gc);
+       }
+
+       XSync (evaspixmapsink->xcontext->disp, FALSE);
+
+       g_mutex_unlock (evaspixmapsink->x_lock);
+
+       g_free (xpixmap);
+}
+
+static void
+gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx)
+{
+       Window root_window;
+       XWindowAttributes root_attr;
+
+       int cur_pixmap_x = 0;
+       int cur_pixmap_y = 0;
+       unsigned int cur_pixmap_width = 0;
+       unsigned int cur_pixmap_height = 0;
+       unsigned int cur_pixmap_border_width = 0;
+       unsigned int cur_pixmap_depth = 0;
+
+       g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
+
+       /* Update the window geometry */
+       g_mutex_lock (evaspixmapsink->x_lock);
+       if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
+               g_mutex_unlock (evaspixmapsink->x_lock);
+               return;
+       }
+
+       /* Get root window and size of current pixmap */
+       XGetGeometry( evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[idx]->pixmap, &root_window,
+                       &cur_pixmap_x, &cur_pixmap_y, /* relative x, y, for pixmap these are alway 0 */
+                       &cur_pixmap_width, &cur_pixmap_height,
+                       &cur_pixmap_border_width, &cur_pixmap_depth ); /* cur_pixmap_border_width, cur_pixmap_depth are not used */
+
+       evaspixmapsink->xpixmap[idx]->width = cur_pixmap_width;
+       evaspixmapsink->xpixmap[idx]->height = cur_pixmap_height;
+
+       evaspixmapsink->xpixmap[idx]->x = cur_pixmap_x;
+       evaspixmapsink->xpixmap[idx]->y = cur_pixmap_y;
+
+       /* Get size of root window == size of screen */
+       XGetWindowAttributes(evaspixmapsink->xcontext->disp, root_window, &root_attr);
+
+       evaspixmapsink->scr_w = root_attr.width;
+       evaspixmapsink->scr_h = root_attr.height;
+
+       if (!evaspixmapsink->have_render_rect) {
+               evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y = 0;
+               evaspixmapsink->render_rect.w = cur_pixmap_width;
+               evaspixmapsink->render_rect.h = cur_pixmap_height;
+       }
+
+       GST_LOG_OBJECT (evaspixmapsink,"screen size %dx%d, current pixmap geometry %d,%d,%dx%d, render_rect %d,%d,%dx%d",
+                       evaspixmapsink->scr_w, evaspixmapsink->scr_h,
+                       evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y,
+                       evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
+                       evaspixmapsink->render_rect.x, evaspixmapsink->render_rect.y,
+                       evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h);
+
+       g_mutex_unlock (evaspixmapsink->x_lock);
+}
+
+static void
+gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
+{
+       g_return_if_fail (xpixmap != NULL);
+       g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
+
+       if (!xpixmap->pixmap) {
+               GST_WARNING_OBJECT (evaspixmapsink,"pixmap was not created..");
+               return;
+       }
+
+       g_mutex_lock (evaspixmapsink->x_lock);
+
+       if (!evaspixmapsink->xcontext) {
+               GST_WARNING_OBJECT (evaspixmapsink,"xcontext is null..");
+               g_mutex_unlock (evaspixmapsink->x_lock);
+               return;
+       }
+
+       if (evaspixmapsink->stop_video) {
+               XvStopVideo (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, xpixmap->pixmap);
+       }
+       XSync (evaspixmapsink->xcontext->disp, FALSE);
+
+       g_mutex_unlock (evaspixmapsink->x_lock);
+
+       g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
+       evaspixmapsink->last_updated_idx = -1;
+       xpixmap->ref = 0;
+       xpixmap->damaged_time = 0;
+       g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
+}
+
+/* This function commits our internal colorbalance settings to our grabbed Xv
+   port. If the xcontext is not initialized yet it simply returns */
+static void
+gst_evaspixmapsink_update_colorbalance (GstEvasPixmapSink *evaspixmapsink)
+{
+  GList *channels = NULL;
+
+  g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
+
+  /* If we haven't initialized the X context we can't update anything */
+  if (evaspixmapsink->xcontext == NULL)
+    return;
+
+  /* Don't set the attributes if they haven't been changed, to avoid
+   * rounding errors changing the values */
+  if (!evaspixmapsink->cb_changed)
+    return;
+
+  /* For each channel of the colorbalance we calculate the correct value
+     doing range conversion and then set the Xv port attribute to match our
+     values. */
+  channels = evaspixmapsink->xcontext->channels_list;
+
+  while (channels) {
+    if (channels->data && GST_IS_COLOR_BALANCE_CHANNEL (channels->data)) {
+      GstColorBalanceChannel *channel = NULL;
+      Atom prop_atom;
+      gint value = 0;
+      gdouble convert_coef;
+
+      channel = GST_COLOR_BALANCE_CHANNEL (channels->data);
+      g_object_ref (channel);
+
+      /* Our range conversion coef */
+      convert_coef = (channel->max_value - channel->min_value) / 2000.0;
+
+      if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
+        value = evaspixmapsink->hue;
+      } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
+        value = evaspixmapsink->saturation;
+      } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
+        value = evaspixmapsink->contrast;
+      } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
+        value = evaspixmapsink->brightness;
+      } else {
+        g_warning ("got an unknown channel %s", channel->label);
+        g_object_unref (channel);
+        return;
+      }
+
+      /* Committing to Xv port */
+      g_mutex_lock (evaspixmapsink->x_lock);
+      prop_atom =
+          XInternAtom (evaspixmapsink->xcontext->disp, channel->label, True);
+      if (prop_atom != None) {
+        int xv_value;
+        xv_value =
+            floor (0.5 + (value + 1000) * convert_coef + channel->min_value);
+        XvSetPortAttribute (evaspixmapsink->xcontext->disp,
+            evaspixmapsink->xcontext->xv_port_id, prop_atom, xv_value);
+      }
+      g_mutex_unlock (evaspixmapsink->x_lock);
+
+      g_object_unref (channel);
+    }
+    channels = g_list_next (channels);
+  }
+}
+
+static void
+gst_lookup_xv_port_from_adaptor (GstXContext *xcontext, XvAdaptorInfo *adaptors, int adaptor_no)
+{
+  gint j;
+  gint res;
+
+  /* Do we support XvImageMask ? */
+  if (!(adaptors[adaptor_no].type & XvImageMask)) {
+    GST_DEBUG ("XV Adaptor %s has no support for XvImageMask", adaptors[adaptor_no].name);
+    return;
+  }
+
+  /* We found such an adaptor, looking for an available port */
+  for (j = 0; j < adaptors[adaptor_no].num_ports && !xcontext->xv_port_id; j++) {
+    /* We try to grab the port */
+    res = XvGrabPort (xcontext->disp, adaptors[adaptor_no].base_id + j, 0);
+    if (Success == res) {
+      xcontext->xv_port_id = adaptors[adaptor_no].base_id + j;
+      GST_DEBUG ("XV Adaptor %s with %ld ports", adaptors[adaptor_no].name, adaptors[adaptor_no].num_ports);
+    } else {
+      GST_DEBUG ("GrabPort %d for XV Adaptor %s failed: %d", j, adaptors[adaptor_no].name, res);
+    }
+  }
+}
+
+/* This function generates a caps with all supported format by the first
+   Xv grabable port we find. We store each one of the supported formats in a
+   format list and append the format to a newly created caps that we return
+   If this function does not return NULL because of an error, it also grabs
+   the port via XvGrabPort */
+static GstCaps*
+gst_evaspixmapsink_get_xv_support (GstEvasPixmapSink *evaspixmapsink, GstXContext *xcontext)
+{
+  gint i;
+  XvAdaptorInfo *adaptors;
+  gint nb_formats;
+  XvImageFormatValues *formats = NULL;
+  guint nb_encodings;
+  XvEncodingInfo *encodings = NULL;
+  gulong max_w = G_MAXINT, max_h = G_MAXINT;
+  GstCaps *caps = NULL;
+  GstCaps *rgb_caps = NULL;
+
+  g_return_val_if_fail (xcontext != NULL, NULL);
+
+  /* First let's check that XVideo extension is available */
+  if (!XQueryExtension (xcontext->disp, "XVideo", &i, &i, &i)) {
+    GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
+        ("Could not initialise Xv output"),
+        ("XVideo extension is not available"));
+    return NULL;
+  }
+
+  /* Then we get adaptors list */
+  if (Success != XvQueryAdaptors (xcontext->disp, xcontext->root,
+          &xcontext->nb_adaptors, &adaptors)) {
+    GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
+        ("Could not initialise Xv output"),
+        ("Failed getting XV adaptors list"));
+    return NULL;
+  }
+
+  xcontext->xv_port_id = 0;
+
+  GST_DEBUG_OBJECT (evaspixmapsink,"Found %u XV adaptor(s)", xcontext->nb_adaptors);
+
+  xcontext->adaptors =
+      (gchar **) g_malloc0 (xcontext->nb_adaptors * sizeof (gchar *));
+
+  /* Now fill up our adaptor name array */
+  for (i = 0; i < xcontext->nb_adaptors; i++) {
+    xcontext->adaptors[i] = g_strdup (adaptors[i].name);
+  }
+
+  if (evaspixmapsink->adaptor_no < xcontext->nb_adaptors) {
+    /* Find xv port from user defined adaptor */
+    gst_lookup_xv_port_from_adaptor (xcontext, adaptors, evaspixmapsink->adaptor_no);
+  }
+
+  if (!xcontext->xv_port_id) {
+    /* Now search for an adaptor that supports XvImageMask */
+    for (i = 0; i < xcontext->nb_adaptors && !xcontext->xv_port_id; i++) {
+      gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i);
+      evaspixmapsink->adaptor_no = i;
+    }
+  }
+
+  XvFreeAdaptorInfo (adaptors);
+
+  if (!xcontext->xv_port_id) {
+    evaspixmapsink->adaptor_no = -1;
+    GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, BUSY,
+        ("Could not initialise Xv output"), ("No port available"));
+    return NULL;
+  }
+
+  /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */
+  {
+    int count, todo = 3;
+    XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp,
+        xcontext->xv_port_id, &count);
+    static const char autopaint[] = "XV_AUTOPAINT_COLORKEY";
+    static const char dbl_buffer[] = "XV_DOUBLE_BUFFER";
+    static const char colorkey[] = "XV_COLORKEY";
+
+    GST_DEBUG_OBJECT (evaspixmapsink,"Checking %d Xv port attributes", count);
+
+    evaspixmapsink->have_autopaint_colorkey = FALSE;
+    evaspixmapsink->have_double_buffer = FALSE;
+    evaspixmapsink->have_colorkey = FALSE;
+
+    for (i = 0; ((i < count) && todo); i++)
+      if (!strcmp (attr[i].name, autopaint)) {
+        const Atom atom = XInternAtom (xcontext->disp, autopaint, False);
+
+        /* turn on autopaint colorkey */
+        XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
+            (evaspixmapsink->autopaint_colorkey ? 1 : 0));
+        todo--;
+        evaspixmapsink->have_autopaint_colorkey = TRUE;
+      } else if (!strcmp (attr[i].name, dbl_buffer)) {
+        const Atom atom = XInternAtom (xcontext->disp, dbl_buffer, False);
+
+        XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
+            (evaspixmapsink->double_buffer ? 1 : 0));
+        todo--;
+        evaspixmapsink->have_double_buffer = TRUE;
+      } else if (!strcmp (attr[i].name, colorkey)) {
+        /* Set the colorkey, default is something that is dark but hopefully
+         * won't randomly appear on the screen elsewhere (ie not black or greys)
+         * can be overridden by setting "colorkey" property
+         */
+        const Atom atom = XInternAtom (xcontext->disp, colorkey, False);
+        guint32 ckey = 0;
+        gboolean set_attr = TRUE;
+        guint cr, cg, cb;
+
+        /* set a colorkey in the right format RGB565/RGB888
+         * We only handle these 2 cases, because they're the only types of
+         * devices we've encountered. If we don't recognise it, leave it alone
+         */
+        cr = (evaspixmapsink->colorkey >> 16);
+        cg = (evaspixmapsink->colorkey >> 8) & 0xFF;
+        cb = (evaspixmapsink->colorkey) & 0xFF;
+        switch (xcontext->depth) {
+          case 16:             /* RGB 565 */
+            cr >>= 3;
+            cg >>= 2;
+            cb >>= 3;
+            ckey = (cr << 11) | (cg << 5) | cb;
+            break;
+          case 24:
+          case 32:             /* RGB 888 / ARGB 8888 */
+            ckey = (cr << 16) | (cg << 8) | cb;
+            break;
+          default:
+            GST_DEBUG_OBJECT (evaspixmapsink,"Unknown bit depth %d for Xv Colorkey - not adjusting", xcontext->depth);
+            set_attr = FALSE;
+            break;
+        }
+
+        if (set_attr) {
+          ckey = CLAMP (ckey, (guint32) attr[i].min_value,
+              (guint32) attr[i].max_value);
+          GST_LOG_OBJECT (evaspixmapsink,"Setting color key for display depth %d to 0x%x", xcontext->depth, ckey);
+
+          XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
+              (gint) ckey);
+        }
+        todo--;
+        evaspixmapsink->have_colorkey = TRUE;
+      }
+
+    XFree (attr);
+  }
+
+  /* Get the list of encodings supported by the adapter and look for the
+   * XV_IMAGE encoding so we can determine the maximum width and height
+   * supported */
+  XvQueryEncodings (xcontext->disp, xcontext->xv_port_id, &nb_encodings,
+      &encodings);
+
+  for (i = 0; i < nb_encodings; i++) {
+    GST_LOG_OBJECT (evaspixmapsink,
+        "Encoding %d, name %s, max wxh %lux%lu rate %d/%d",
+        i, encodings[i].name, encodings[i].width, encodings[i].height,
+        encodings[i].rate.numerator, encodings[i].rate.denominator);
+    if (strcmp (encodings[i].name, "XV_IMAGE") == 0) {
+      max_w = encodings[i].width;
+      max_h = encodings[i].height;
+      evaspixmapsink->scr_w = max_w;
+      evaspixmapsink->scr_h = max_h;
+    }
+  }
+
+  XvFreeEncodingInfo (encodings);
+
+  /* We get all image formats supported by our port */
+  formats = XvListImageFormats (xcontext->disp,
+      xcontext->xv_port_id, &nb_formats);
+  caps = gst_caps_new_empty ();
+  for (i = 0; i < nb_formats; i++) {
+    GstCaps *format_caps = NULL;
+    gboolean is_rgb_format = FALSE;
+
+    /* We set the image format of the xcontext to an existing one. This
+       is just some valid image format for making our xshm calls check before
+       caps negotiation really happens. */
+    xcontext->im_format = formats[i].id;
+
+    switch (formats[i].type) {
+      case XvRGB:
+      {
+        XvImageFormatValues *fmt = &(formats[i]);
+        gint endianness = G_BIG_ENDIAN;
+
+        if (fmt->byte_order == LSBFirst) {
+          /* our caps system handles 24/32bpp RGB as big-endian. */
+          if (fmt->bits_per_pixel == 24 || fmt->bits_per_pixel == 32) {
+            fmt->red_mask = GUINT32_TO_BE (fmt->red_mask);
+            fmt->green_mask = GUINT32_TO_BE (fmt->green_mask);
+            fmt->blue_mask = GUINT32_TO_BE (fmt->blue_mask);
+
+            if (fmt->bits_per_pixel == 24) {
+              fmt->red_mask >>= 8;
+              fmt->green_mask >>= 8;
+              fmt->blue_mask >>= 8;
+            }
+          } else
+            endianness = G_LITTLE_ENDIAN;
+        }
+
+        format_caps = gst_caps_new_simple ("video/x-raw-rgb",
+            "format", GST_TYPE_FOURCC, formats[i].id,
+            "endianness", G_TYPE_INT, endianness,
+            "depth", G_TYPE_INT, fmt->depth,
+            "bpp", G_TYPE_INT, fmt->bits_per_pixel,
+            "red_mask", G_TYPE_INT, fmt->red_mask,
+            "green_mask", G_TYPE_INT, fmt->green_mask,
+            "blue_mask", G_TYPE_INT, fmt->blue_mask,
+            "width", GST_TYPE_INT_RANGE, 1, max_w,
+            "height", GST_TYPE_INT_RANGE, 1, max_h,
+            "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
+
+        is_rgb_format = TRUE;
+        break;
+      }
+      case XvYUV:
+        format_caps = gst_caps_new_simple ("video/x-raw-yuv",
+            "format", GST_TYPE_FOURCC, formats[i].id,
+            "width", GST_TYPE_INT_RANGE, 1, max_w,
+            "height", GST_TYPE_INT_RANGE, 1, max_h,
+            "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
+        break;
+      default:
+        g_assert_not_reached ();
+        break;
+    }
+
+    if (format_caps) {
+      GstEvasPixmapFormat *format = NULL;
+
+      format = g_new0 (GstEvasPixmapFormat, 1);
+      if (format) {
+        format->format = formats[i].id;
+        format->caps = gst_caps_copy (format_caps);
+        xcontext->formats_list = g_list_append (xcontext->formats_list, format);
+      }
+
+      if (is_rgb_format) {
+        if (rgb_caps == NULL)
+          rgb_caps = format_caps;
+        else
+          gst_caps_append (rgb_caps, format_caps);
+      } else
+        gst_caps_append (caps, format_caps);
+    }
+  }
+
+  /* Collected all caps into either the caps or rgb_caps structures.
+   * Append rgb_caps on the end of YUV, so that YUV is always preferred */
+  if (rgb_caps)
+    gst_caps_append (caps, rgb_caps);
+
+  if (formats)
+    XFree (formats);
+
+  GST_DEBUG_OBJECT (evaspixmapsink,"Generated the following caps: %" GST_PTR_FORMAT, caps);
+
+  if (gst_caps_is_empty (caps)) {
+    gst_caps_unref (caps);
+    XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
+    GST_ELEMENT_ERROR (evaspixmapsink, STREAM, WRONG_TYPE, (NULL),
+        ("No supported format found"));
+    return NULL;
+  }
+
+  return caps;
+}
+
+static gpointer
+gst_evaspixmapsink_event_thread (GstEvasPixmapSink * evaspixmapsink)
+{
+       g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
+       int damage_base = 0;
+       int damage_err_base = 0;
+       int damage_case = 0;
+       XEvent e;
+       int i = 0;
+       Display *disp = NULL;
+
+#ifdef DUMP_IMG
+  int ret = 0;
+  char file_name[128];
+  char *dump_data;
+#endif
+
+
+       GST_OBJECT_LOCK (evaspixmapsink);
+
+       if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->disp) {
+               disp = evaspixmapsink->xcontext->disp;
+       } else {
+               GST_ERROR_OBJECT (evaspixmapsink,"evaspixmapsink->xcontext(->disp) is not ready");
+               return NULL;
+       }
+
+       if (!XDamageQueryExtension(evaspixmapsink->xcontext->disp, &damage_base, &damage_err_base)) {
+               GST_ERROR_OBJECT (evaspixmapsink,"XDamageQueryExtension() failed");
+               return NULL;
+       }
+       damage_case = (int)damage_base + XDamageNotify;
+
+       while (evaspixmapsink->running) {
+               GST_OBJECT_UNLOCK (evaspixmapsink);
+
+               g_mutex_lock (evaspixmapsink->x_lock);
+               while (XPending (disp)) {
+                       XNextEvent (disp, &e);
+                       g_mutex_unlock (evaspixmapsink->x_lock);
+                       if (e.type == damage_case ) {
+                               XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&e;
+                               for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+                                       GstXPixmap *xpixmap = evaspixmapsink->xpixmap[i];
+                                       if (xpixmap && damage_ev->drawable == xpixmap->pixmap) {
+                                               g_mutex_lock(evaspixmapsink->pixmap_ref_lock);
+                                               if (xpixmap->ref) {
+                                                       /* set it only if damage event comes from _buffer_put() */
+                                                       xpixmap->damaged_time = (gint)get_millis_time();
+                                               }
+                                               g_mutex_unlock(evaspixmapsink->pixmap_ref_lock);
+                                               if (GST_STATE(evaspixmapsink) < GST_STATE_PLAYING || log_warn_count < 20) {
+                                                       GST_WARNING_OBJECT (evaspixmapsink,"event_handler : got a damage event for pixmap(%d), refcount(%d), damaged_time(%d)",
+                                                                                       xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time);
+                                               } else {
+                                                       GST_DEBUG_OBJECT (evaspixmapsink,"event_handler : got a damage event for pixmap(%d), refcount(%d), damaged_time(%d)",
+                                                                                       xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time);
+                                               }
+                                               if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
+                                                       GST_WARNING_OBJECT (evaspixmapsink,"event_handler : epipe_request_count(%d), skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
+                                               } else {
+                                                       ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink));
+                                                       evaspixmapsink->epipe_request_count++;
+                                                       if (GST_STATE(evaspixmapsink) < GST_STATE_PLAYING || log_warn_count < 20 ) {
+                                                               GST_WARNING_OBJECT (evaspixmapsink,"event_handler : after call ecore_pipe_write() for pixmap(%d)", xpixmap->pixmap);
+                                                               log_warn_count++;
+                                                       } else {
+                                                               GST_DEBUG_OBJECT (evaspixmapsink,"event_handler : after call ecore_pipe_write() for pixmap(%d)", xpixmap->pixmap);
+                                                       }
+                                               }
+                                               g_mutex_lock (evaspixmapsink->x_lock);
+                                               XDamageSubtract (evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i], None, None );
+                                               g_mutex_unlock (evaspixmapsink->x_lock);
+
+#ifdef DUMP_IMG
+            int dump_w = evaspixmapsink->w + (32 - (evaspixmapsink->w%32)); // for multiples of 32
+            if(g_cnt<100)
+            {
+              evaspixmapsink->pixmap_addr[i] = gst_evaspixmapsink_get_buffer(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, dump_w, evaspixmapsink->h, i);
+              GST_ERROR("<DUMP_%2.2d> pixmap[%d] addr %p (w : %d, h : %d)", g_cnt, i, evaspixmapsink->pixmap_addr[i], dump_w, evaspixmapsink->h);
+              sprintf(file_name, "/opt/usr/media/DUMP_%2.2d.dump", g_cnt);
+
+              dump_data = g_malloc(dump_w * evaspixmapsink->h * 4);
+              memcpy (dump_data, evaspixmapsink->pixmap_addr[i], dump_w * evaspixmapsink->h * 4);
+
+              ret = util_write_rawdata(file_name, dump_data, dump_w * evaspixmapsink->h * 4);
+              if (ret) {
+                GST_ERROR_OBJECT (evaspixmapsink, "util_write_rawdata() failed");
+              }
+              else
+                g_cnt++;
+              g_free(dump_data);
+
+              if (g_bufinfo[i]) {
+                gst_evaspixmapsink_free_buffer (i);
+                g_bufinfo[i] = NULL;
+              }
+              evaspixmapsink->pixmap_addr[i] = NULL;
+            }
+#endif
+                                               if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
+                                                       if (GST_STATE(evaspixmapsink) == GST_STATE_PLAYING) {
+                                                               drm_fini_close_gem_handle(evaspixmapsink, xpixmap->pixmap);
+                                                       }
+                                               }
+                                               break;
+                                       }
+                               }
+                               if (i == evaspixmapsink->num_of_pixmaps) {
+                                       GST_WARNING_OBJECT (evaspixmapsink,"event_handler : could not find corresponding pixmap with this damage event(%d)", damage_ev->drawable);
+                               }
+                       } else {
+                               GST_LOG_OBJECT (evaspixmapsink,"event_handler : unidentified event(%d)", e.type);
+                               g_mutex_lock (evaspixmapsink->x_lock);
+                               continue;
+                       }
+                       g_mutex_lock (evaspixmapsink->x_lock);
+               }
+               //XSync (disp, FALSE);
+               g_mutex_unlock (evaspixmapsink->x_lock);
+
+               g_usleep (G_USEC_PER_SEC / 40);
+               GST_OBJECT_LOCK (evaspixmapsink);
+       }
+       GST_OBJECT_UNLOCK (evaspixmapsink);
+       return NULL;
+}
+
+static void
+gst_evaspixmapsink_manage_event_thread (GstEvasPixmapSink *evaspixmapsink)
+{
+       /* don't start the thread too early */
+       if (evaspixmapsink->xcontext == NULL) {
+               GST_ERROR_OBJECT (evaspixmapsink,"xcontext is NULL..");
+               return;
+       }
+
+       GST_OBJECT_LOCK (evaspixmapsink);
+
+       if (!evaspixmapsink->event_thread) {
+               /* Setup our event listening thread */
+               GST_DEBUG_OBJECT (evaspixmapsink,"run xevent thread");
+               evaspixmapsink->running = TRUE;
+               evaspixmapsink->event_thread = g_thread_create ( (GThreadFunc) gst_evaspixmapsink_event_thread, evaspixmapsink, TRUE, NULL);
+       } else {
+               GST_WARNING_OBJECT (evaspixmapsink,"there already existed the event_thread.. keep going");
+               /* Do not finalize the thread in here, Only finalize the thread by calling gst_evaspixmapsink_reset() */
+       }
+
+       GST_OBJECT_UNLOCK (evaspixmapsink);
+}
+
+
+/* This function calculates the pixel aspect ratio based on the properties
+ * in the xcontext structure and stores it there. */
+static void
+gst_evaspixmapsink_calculate_pixel_aspect_ratio (GstXContext *xcontext)
+{
+  static const gint par[][2] = {
+    {1, 1},                     /* regular screen */
+    {16, 15},                   /* PAL TV */
+    {11, 10},                   /* 525 line Rec.601 video */
+    {54, 59},                   /* 625 line Rec.601 video */
+    {64, 45},                   /* 1280x1024 on 16:9 display */
+    {5, 3},                     /* 1280x1024 on 4:3 display */
+    {4, 3}                      /*  800x600 on 16:9 display */
+  };
+  gint i;
+  gint index;
+  gdouble ratio;
+  gdouble delta;
+
+#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
+
+  /* first calculate the "real" ratio based on the X values;
+   * which is the "physical" w/h divided by the w/h in pixels of the display */
+  ratio = (gdouble) (xcontext->widthmm * xcontext->height)
+      / (xcontext->heightmm * xcontext->width);
+
+  /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
+   * override here */
+  if (xcontext->width == 720 && xcontext->height == 576) {
+    ratio = 4.0 * 576 / (3.0 * 720);
+  }
+  GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
+  /* now find the one from par[][2] with the lowest delta to the real one */
+  delta = DELTA (0);
+  index = 0;
+
+  for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
+    gdouble this_delta = DELTA (i);
+
+    if (this_delta < delta) {
+      index = i;
+      delta = this_delta;
+    }
+  }
+
+  GST_DEBUG ("Decided on index %d (%d/%d)", index,
+      par[index][0], par[index][1]);
+
+  g_free (xcontext->par);
+  xcontext->par = g_new0 (GValue, 1);
+  g_value_init (xcontext->par, GST_TYPE_FRACTION);
+  gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]);
+  GST_DEBUG ("set xcontext PAR to %d/%d",
+      gst_value_get_fraction_numerator (xcontext->par),
+      gst_value_get_fraction_denominator (xcontext->par));
+}
+
+/* This function gets the X Display and global info about it. Everything is
+   stored in our object and will be cleaned when the object is disposed. Note
+   here that caps for supported format are generated without any window or
+   image creation */
+static GstXContext*
+gst_evaspixmapsink_xcontext_get (GstEvasPixmapSink *evaspixmapsink)
+{
+       GstXContext *xcontext = NULL;
+       XPixmapFormatValues *px_formats = NULL;
+       gint nb_formats = 0, i, j, N_attr;
+       XvAttribute *xv_attr;
+       Atom prop_atom;
+       const char *channels[4] = { "XV_HUE", "XV_SATURATION", "XV_BRIGHTNESS", "XV_CONTRAST"};
+
+       g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
+
+       xcontext = g_new0 (GstXContext, 1);
+       xcontext->im_format = 0;
+
+       g_mutex_lock (evaspixmapsink->x_lock);
+
+       xcontext->disp = XOpenDisplay (evaspixmapsink->display_name);
+       if (!xcontext->disp) {
+               g_mutex_unlock (evaspixmapsink->x_lock);
+               g_free (xcontext);
+               GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Could not initialise Xv output"), ("Could not open display"));
+               return NULL;
+       }
+       GST_WARNING_OBJECT (evaspixmapsink,"Display(0x%x) is opened", xcontext->disp);
+       g_my_disp = xcontext->disp;
+
+       xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
+       xcontext->screen_num = DefaultScreen (xcontext->disp);
+       xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
+       xcontext->root = DefaultRootWindow (xcontext->disp);
+       xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
+       xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
+
+       xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num);
+       xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num);
+       xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num);
+       xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num);
+
+       GST_DEBUG_OBJECT (evaspixmapsink,"X reports %dx%d pixels and %d mm x %d mm", xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
+
+       gst_evaspixmapsink_calculate_pixel_aspect_ratio (xcontext);
+       /* We get supported pixmap formats at supported depth */
+       px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
+
+       if (!px_formats) {
+               XCloseDisplay (xcontext->disp);
+               g_mutex_unlock (evaspixmapsink->x_lock);
+               g_free (xcontext->par);
+               g_free (xcontext);
+               GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
+               ("Could not initialise Xv output"), ("Could not get pixel formats"));
+               g_my_disp = NULL;
+               return NULL;
+       }
+
+       /* We get bpp value corresponding to our running depth */
+       for (i = 0; i < nb_formats; i++) {
+               if (px_formats[i].depth == xcontext->depth)
+               xcontext->bpp = px_formats[i].bits_per_pixel;
+       }
+
+       XFree (px_formats);
+
+       xcontext->endianness = (ImageByteOrder (xcontext->disp) == LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
+
+       /* our caps system handles 24/32bpp RGB as big-endian. */
+       if ((xcontext->bpp == 24 || xcontext->bpp == 32) && xcontext->endianness == G_LITTLE_ENDIAN) {
+               xcontext->endianness = G_BIG_ENDIAN;
+               xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
+               xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
+               xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
+               if (xcontext->bpp == 24) {
+                       xcontext->visual->red_mask >>= 8;
+                       xcontext->visual->green_mask >>= 8;
+                       xcontext->visual->blue_mask >>= 8;
+               }
+       }
+
+       xcontext->caps = gst_evaspixmapsink_get_xv_support (evaspixmapsink, xcontext);
+
+       if (!xcontext->caps) {
+               XCloseDisplay (xcontext->disp);
+               g_mutex_unlock (evaspixmapsink->x_lock);
+               g_free (xcontext->par);
+               g_free (xcontext);
+               /* GST_ELEMENT_ERROR is thrown by gst_evaspixmapsink_get_xv_support */
+               g_my_disp = NULL;
+               return NULL;
+       }
+#ifdef HAVE_XSHM
+       /* Search for XShm extension support */
+       if (XShmQueryExtension (xcontext->disp) && gst_evaspixmapsink_check_xshm_calls (xcontext)) {
+               xcontext->use_xshm = TRUE;
+               GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is using XShm extension");
+       } else
+#endif /* HAVE_XSHM */
+       {
+               xcontext->use_xshm = FALSE;
+               GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is not using XShm extension");
+       }
+
+       xv_attr = XvQueryPortAttributes (xcontext->disp, xcontext->xv_port_id, &N_attr);
+
+       /* Generate the channels list */
+       for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) {
+               XvAttribute *matching_attr = NULL;
+
+               /* Retrieve the property atom if it exists. If it doesn't exist,
+               * the attribute itself must not either, so we can skip */
+               prop_atom = XInternAtom (xcontext->disp, channels[i], True);
+               if (prop_atom == None) {
+                       continue;
+               }
+
+               if (xv_attr != NULL) {
+                       for (j = 0; j < N_attr && matching_attr == NULL; ++j) {
+                               if (!g_ascii_strcasecmp (channels[i], xv_attr[j].name)) {
+                                       matching_attr = xv_attr + j;
+                               }
+                       }
+               }
+
+               if (matching_attr) {
+                       GstColorBalanceChannel *channel;
+                       channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
+                       channel->label = g_strdup (channels[i]);
+                       channel->min_value = matching_attr->min_value;
+                       channel->max_value = matching_attr->max_value;
+
+                       xcontext->channels_list = g_list_append (xcontext->channels_list, channel);
+
+                       /* If the colorbalance settings have not been touched we get Xv values
+                               as defaults and update our internal variables */
+                       if (!evaspixmapsink->cb_changed) {
+                               gint val;
+                               XvGetPortAttribute (xcontext->disp, xcontext->xv_port_id, prop_atom, &val);
+                               /* Normalize val to [-1000, 1000] */
+                               val = floor (0.5 + -1000 + 2000 * (val - channel->min_value) /  (double) (channel->max_value - channel->min_value));
+
+                               if (!g_ascii_strcasecmp (channels[i], "XV_HUE")) {
+                                       evaspixmapsink->hue = val;
+                               } else if (!g_ascii_strcasecmp (channels[i], "XV_SATURATION")) {
+                                       evaspixmapsink->saturation = val;
+                               } else if (!g_ascii_strcasecmp (channels[i], "XV_BRIGHTNESS")) {
+                                       evaspixmapsink->brightness = val;
+                               } else if (!g_ascii_strcasecmp (channels[i], "XV_CONTRAST")) {
+                                       evaspixmapsink->contrast = val;
+                               }
+                       }
+               }
+       }
+
+       if (xv_attr) {
+               XFree (xv_attr);
+       }
+
+       g_mutex_unlock (evaspixmapsink->x_lock);
+
+       return xcontext;
+}
+
+/* This function cleans the X context. Closing the Display, releasing the XV
+   port and unrefing the caps for supported formats. */
+static void
+gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink)
+{
+  GList *formats_list, *channels_list;
+  GstXContext *xcontext;
+  gint i = 0;
+
+  g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
+
+  GST_OBJECT_LOCK (evaspixmapsink);
+  if (evaspixmapsink->xcontext == NULL) {
+    GST_OBJECT_UNLOCK (evaspixmapsink);
+    return;
+  }
+
+  /* Take the XContext from the sink and clean it up */
+  xcontext = evaspixmapsink->xcontext;
+  evaspixmapsink->xcontext = NULL;
+
+  GST_OBJECT_UNLOCK (evaspixmapsink);
+
+  formats_list = xcontext->formats_list;
+
+  while (formats_list) {
+    GstEvasPixmapFormat *format = formats_list->data;
+
+    gst_caps_unref (format->caps);
+    g_free (format);
+    formats_list = g_list_next (formats_list);
+  }
+
+  if (xcontext->formats_list)
+    g_list_free (xcontext->formats_list);
+
+  channels_list = xcontext->channels_list;
+
+  while (channels_list) {
+    GstColorBalanceChannel *channel = channels_list->data;
+
+    g_object_unref (channel);
+    channels_list = g_list_next (channels_list);
+  }
+
+  if (xcontext->channels_list)
+    g_list_free (xcontext->channels_list);
+
+  gst_caps_unref (xcontext->caps);
+
+  for (i = 0; i < xcontext->nb_adaptors; i++) {
+    g_free (xcontext->adaptors[i]);
+  }
+
+  g_free (xcontext->adaptors);
+
+  g_free (xcontext->par);
+
+  g_mutex_lock (evaspixmapsink->x_lock);
+
+  GST_DEBUG_OBJECT (evaspixmapsink,"Closing display and freeing X Context");
+
+  XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
+
+  XCloseDisplay (xcontext->disp);
+  g_my_disp = NULL;
+
+  g_mutex_unlock (evaspixmapsink->x_lock);
+
+  g_free (xcontext);
+}
+
+/* Element stuff */
+
+/* This function tries to get a format matching with a given caps in the
+   supported list of formats we generated in gst_evaspixmapsink_get_xv_support */
+static gint
+gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
+{
+  GList *list = NULL;
+
+  g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
+
+  list = evaspixmapsink->xcontext->formats_list;
+
+  while (list) {
+    GstEvasPixmapFormat *format = list->data;
+
+    if (format) {
+      if (gst_caps_can_intersect (caps, format->caps)) {
+        return format->format;
+      }
+    }
+    list = g_list_next (list);
+  }
+
+  return -1;
+}
+
+static GstCaps *
+gst_evaspixmapsink_getcaps (GstBaseSink *bsink)
+{
+  GstEvasPixmapSink *evaspixmapsink;
+
+  evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
+
+  if (evaspixmapsink->xcontext)
+    return gst_caps_ref (evaspixmapsink->xcontext->caps);
+
+  return
+      gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
+          (evaspixmapsink)));
+}
+
+static gboolean
+gst_evaspixmapsink_setcaps (GstBaseSink *bsink, GstCaps *caps)
+{
+       GstEvasPixmapSink *evaspixmapsink;
+       GstStructure *structure;
+       guint32 im_format = 0;
+       gboolean ret;
+       gint video_width, video_height;
+       gint disp_x, disp_y;
+       gint disp_width, disp_height;
+       gint video_par_n, video_par_d;        /* video's PAR */
+       gint display_par_n, display_par_d;    /* display's PAR */
+       const GValue *caps_par;
+       const GValue *caps_disp_reg;
+       const GValue *fps;
+       guint num, den;
+       gboolean enable_last_buffer;
+
+       evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
+
+       GST_DEBUG_OBJECT (evaspixmapsink,"In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %" GST_PTR_FORMAT, evaspixmapsink->xcontext->caps, caps);
+
+       if (!gst_caps_can_intersect (evaspixmapsink->xcontext->caps, caps)) {
+               goto incompatible_caps;
+       }
+
+       structure = gst_caps_get_structure (caps, 0);
+       ret = gst_structure_get_int (structure, "width", &video_width);
+       ret &= gst_structure_get_int (structure, "height", &video_height);
+       fps = gst_structure_get_value (structure, "framerate");
+       ret &= (fps != NULL);
+
+       if (!ret) {
+               goto incomplete_caps;
+       }
+
+       evaspixmapsink->aligned_width = video_width;
+       evaspixmapsink->aligned_height = video_height;
+
+       /* get combine prop of hevc */
+       if(gst_structure_get_int (structure, "yuvcombine", &(evaspixmapsink->need_combine_data)))
+       {
+               GST_INFO_OBJECT(evaspixmapsink, "need combine data : %d", evaspixmapsink->need_combine_data);
+       }
+       else
+       {
+               /*Not need to combine data, just directly copy*/
+               evaspixmapsink->need_combine_data = 0;
+       }
+
+       /* get enable-last-buffer */
+       g_object_get(G_OBJECT(evaspixmapsink), "enable-last-buffer", &enable_last_buffer, NULL);
+       GST_INFO_OBJECT (evaspixmapsink,"current enable-last-buffer : %d", enable_last_buffer);
+       /* flush if enable-last-buffer is TRUE */
+       if (enable_last_buffer) {
+               GST_INFO_OBJECT (evaspixmapsink,"flush last-buffer");
+               g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", FALSE, NULL);
+               g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", TRUE, NULL);
+       }
+
+       evaspixmapsink->fps_n = gst_value_get_fraction_numerator (fps);
+       evaspixmapsink->fps_d = gst_value_get_fraction_denominator (fps);
+
+       if (evaspixmapsink->video_width != video_width || evaspixmapsink->video_height != video_height) {
+               evaspixmapsink->src_prev.w = evaspixmapsink->video_width = video_width;
+               evaspixmapsink->src_prev.h = evaspixmapsink->video_height = video_height;
+               evaspixmapsink->need_to_fill_black = TRUE;
+       }
+
+       im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
+       if (im_format == -1) {
+               goto invalid_format;
+       }
+
+       /* get aspect ratio from caps if it's present, and
+       * convert video width and height to a display width and height
+       * using wd / hd = wv / hv * PARv / PARd */
+
+       /* get video's PAR */
+       caps_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
+       if (caps_par) {
+               video_par_n = gst_value_get_fraction_numerator (caps_par);
+               video_par_d = gst_value_get_fraction_denominator (caps_par);
+       } else {
+               video_par_n = 1;
+               video_par_d = 1;
+       }
+       /* get display's PAR */
+       if (evaspixmapsink->par) {
+               display_par_n = gst_value_get_fraction_numerator (evaspixmapsink->par);
+               display_par_d = gst_value_get_fraction_denominator (evaspixmapsink->par);
+       } else {
+               display_par_n = 1;
+               display_par_d = 1;
+       }
+
+       /* get the display region */
+       caps_disp_reg = gst_structure_get_value (structure, "display-region");
+       if (caps_disp_reg) {
+               disp_x = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 0));
+               disp_y = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 1));
+               disp_width = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 2));
+               disp_height = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 3));
+       } else {
+               disp_x = disp_y = 0;
+               disp_width = video_width;
+               disp_height = video_height;
+       }
+
+       if (!gst_video_calculate_display_ratio (&num, &den, video_width, video_height, video_par_n, video_par_d, display_par_n, display_par_d)) {
+               goto no_disp_ratio;
+       }
+
+       evaspixmapsink->disp_x = disp_x;
+       evaspixmapsink->disp_y = disp_y;
+       evaspixmapsink->disp_width = disp_width;
+       evaspixmapsink->disp_height = disp_height;
+
+       GST_DEBUG_OBJECT (evaspixmapsink,"video width/height: %dx%d, calculated display ratio: %d/%d",  video_width, video_height, num, den);
+
+       /* now find a width x height that respects this display ratio.
+       * prefer those that have one of w/h the same as the incoming video
+       * using wd / hd = num / den */
+
+       /* start with same height, because of interlaced video */
+       /* check hd / den is an integer scale factor, and scale wd with the PAR */
+       if (video_height % den == 0) {
+               GST_DEBUG_OBJECT (evaspixmapsink,"keeping video height");
+               GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
+               GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
+       } else if (video_width % num == 0) {
+               GST_DEBUG_OBJECT (evaspixmapsink,"keeping video width");
+               GST_VIDEO_SINK_WIDTH (evaspixmapsink) = video_width;
+               GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_width, den, num);
+       } else {
+               GST_DEBUG_OBJECT (evaspixmapsink,"approximating while keeping video height");
+               GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
+               GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
+       }
+       GST_DEBUG_OBJECT (evaspixmapsink,"scaling to %dx%d", GST_VIDEO_SINK_WIDTH (evaspixmapsink), GST_VIDEO_SINK_HEIGHT (evaspixmapsink));
+
+       /* Creating our window and our image with the display size in pixels */
+       if (GST_VIDEO_SINK_WIDTH (evaspixmapsink) <= 0 || GST_VIDEO_SINK_HEIGHT (evaspixmapsink) <= 0) {
+               goto no_display_size;
+       }
+
+       g_mutex_lock (evaspixmapsink->flow_lock);
+
+       /* We renew our evaspixmap buffer only if size or format changed;
+       * the evaspixmap buffer is the same size as the video pixel size */
+       if ((evaspixmapsink->evas_pixmap_buf) && ((im_format != evaspixmapsink->evas_pixmap_buf->im_format)
+               || (video_width != evaspixmapsink->evas_pixmap_buf->width) || (video_height != evaspixmapsink->evas_pixmap_buf->height))) {
+               GST_DEBUG_OBJECT (evaspixmapsink,"old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
+                               GST_FOURCC_ARGS (evaspixmapsink->evas_pixmap_buf->im_format), GST_FOURCC_ARGS (im_format));
+               GST_DEBUG_OBJECT (evaspixmapsink,"renewing evaspixmap buffer");
+               gst_buffer_unref (GST_BUFFER (evaspixmapsink->evas_pixmap_buf));
+               evaspixmapsink->evas_pixmap_buf = NULL;
+       }
+
+       g_mutex_unlock (evaspixmapsink->flow_lock);
+
+       if (evaspixmapsink->eo) {
+               if (!gst_evaspixmapsink_xpixmap_link (evaspixmapsink)) {
+                       GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
+                       return FALSE;
+               } else {
+                       gst_evaspixmapsink_manage_event_thread (evaspixmapsink);
+               }
+       } else {
+               GST_ERROR_OBJECT (evaspixmapsink,"setcaps success, but there is no evas image object..");
+               return FALSE;
+       }
+
+       return TRUE;
+
+       /* ERRORS */
+       incompatible_caps:
+       {
+               GST_ERROR_OBJECT (evaspixmapsink,"caps incompatible");
+               return FALSE;
+       }
+       incomplete_caps:
+       {
+               GST_DEBUG_OBJECT (evaspixmapsink,"Failed to retrieve either width, ""height or framerate from intersected caps");
+               return FALSE;
+       }
+       invalid_format:
+       {
+               GST_DEBUG_OBJECT (evaspixmapsink,"Could not locate image format from caps %" GST_PTR_FORMAT, caps);
+               return FALSE;
+       }
+       no_disp_ratio:
+       {
+               GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
+               return FALSE;
+       }
+       no_display_size:
+       {
+               GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
+               return FALSE;
+       }
+}
+
+static GstStateChangeReturn
+gst_evaspixmapsink_change_state (GstElement *element, GstStateChange transition)
+{
+       GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+       GstEvasPixmapSink *evaspixmapsink;
+
+       evaspixmapsink = GST_EVASPIXMAPSINK (element);
+
+       switch (transition) {
+       case GST_STATE_CHANGE_NULL_TO_READY:
+               g_mutex_lock (evaspixmapsink->flow_lock);
+               GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_NULL_TO_READY");
+
+               /* open drm to use gem */
+               if (drm_init(evaspixmapsink)) {
+                       GST_ERROR_OBJECT (evaspixmapsink,"drm_init() failure");
+                       g_mutex_unlock (evaspixmapsink->flow_lock);
+                       return GST_STATE_CHANGE_FAILURE;
+               }
+
+               /* check if there exist evas image object, need to write code related to making internal evas image object */
+               if (!is_evas_image_object (evaspixmapsink->eo)) {
+                       GST_ERROR_OBJECT (evaspixmapsink,"There is no evas image object..");
+                       g_mutex_unlock (evaspixmapsink->flow_lock);
+                       return GST_STATE_CHANGE_FAILURE;
+               }
+
+               /* Set xcontext and display */
+               if (!evaspixmapsink->xcontext) {
+                       evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
+                       if (!evaspixmapsink->xcontext) {
+                               GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
+                               g_mutex_unlock (evaspixmapsink->flow_lock);
+                               return GST_STATE_CHANGE_FAILURE;
+                       }
+               }
+
+               /* update object's par with calculated one if not set yet */
+               if (!evaspixmapsink->par) {
+                       evaspixmapsink->par = g_new0 (GValue, 1);
+                       gst_value_init_and_copy (evaspixmapsink->par, evaspixmapsink->xcontext->par);
+                       GST_DEBUG_OBJECT (evaspixmapsink,"set calculated PAR on object's PAR");
+               }
+
+               /* call XSynchronize with the current value of synchronous */
+               GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
+               g_mutex_lock (evaspixmapsink->x_lock);
+               XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
+               g_mutex_unlock (evaspixmapsink->x_lock);
+               gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
+
+               g_mutex_unlock (evaspixmapsink->flow_lock);
+               break;
+
+       case GST_STATE_CHANGE_READY_TO_PAUSED:
+               GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_PAUSED");
+               break;
+
+       case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+               GST_WARNING_OBJECT (evaspixmapsink,"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:
+               GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PLAYING_TO_PAUSED");
+               log_warn_count = 0;
+               break;
+
+       case GST_STATE_CHANGE_PAUSED_TO_READY:
+       {
+               int i = 0;
+               GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PAUSED_TO_READY");
+               evaspixmapsink->fps_n = 0;
+               evaspixmapsink->fps_d = 1;
+               GST_VIDEO_SINK_WIDTH (evaspixmapsink) = 0;
+               GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = 0;
+               drm_fini_close_gem_handle(evaspixmapsink, 0);
+       }
+               break;
+
+       case GST_STATE_CHANGE_READY_TO_NULL:
+               GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_NULL");
+               g_mutex_lock (evaspixmapsink->flow_lock);
+               gst_evaspixmapsink_reset(evaspixmapsink);
+               g_mutex_unlock (evaspixmapsink->flow_lock);
+               /* close drm */
+               drm_fini(evaspixmapsink);
+               break;
+
+       default:
+               break;
+       }
+       return ret;
+}
+
+static void
+gst_evaspixmapsink_get_times (GstBaseSink *bsink, GstBuffer *buf, GstClockTime *start, GstClockTime *end)
+{
+  GstEvasPixmapSink *evaspixmapsink;
+
+  evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
+
+  if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+    *start = GST_BUFFER_TIMESTAMP (buf);
+    if (GST_BUFFER_DURATION_IS_VALID (buf)) {
+      *end = *start + GST_BUFFER_DURATION (buf);
+    } else {
+      if (evaspixmapsink->fps_n > 0) {
+        *end = *start +
+            gst_util_uint64_scale_int (GST_SECOND, evaspixmapsink->fps_d,
+            evaspixmapsink->fps_n);
+      }
+    }
+  }
+}
+
+static void
+gst_evaspixmapsink_combine_i420_scmn_data(GstEvasPixmapSink *evaspixmapsink, GstBuffer *buf)
+{
+       unsigned int outsize = 0;
+       unsigned char *temp_outbuf = evaspixmapsink->evas_pixmap_buf->xvimage->data;
+       int cnt = 0, j = 0;
+       unsigned char *temp_imgb;
+       SCMN_IMGB *imgb = NULL;
+       int stride, w, h, i;
+
+       GST_DEBUG("Begin");
+
+       imgb = (SCMN_IMGB *)GST_BUFFER_DATA(buf);
+       if(imgb == NULL || imgb->a[0] == NULL)
+       {
+               return;
+       }
+
+       stride = GST_ROUND_UP_4 (imgb->w[0]);
+       h = imgb->h[0];
+       w = imgb->w[0];
+       /*Y plane copy */
+       for (i = 0; i < h; i++)
+       {
+               memcpy (temp_outbuf + i * stride, imgb->a[0] + i * imgb->s[0], w);
+       }
+
+       temp_outbuf += GST_ROUND_UP_4 (imgb->w[0]) * GST_ROUND_UP_2 (imgb->h[0]);
+
+       stride = GST_ROUND_UP_4 (GST_ROUND_UP_2 (imgb->w[0]) / 2);
+       h = GST_ROUND_UP_2 (imgb->h[0]) / 2;
+       w = GST_ROUND_UP_2 (imgb->w[0]) / 2;
+       /* Cb plane copy */
+       for (i = 0; i < h; i++)
+       {
+               memcpy (temp_outbuf + i * stride, imgb->a[1] + i * imgb->s[1], w);
+       }
+
+       temp_outbuf += GST_ROUND_UP_4 (GST_ROUND_UP_2 (imgb->w[0]) / 2) * (GST_ROUND_UP_2 (imgb->h[0]) / 2);
+       /* Same stride, height, width as above */
+       /* Cr plane copy */
+       for (i = 0; i < h; i++)
+       {
+               memcpy (temp_outbuf + i * stride, imgb->a[2] + i * imgb->s[2], w);
+       }
+
+       outsize  = imgb->w[0] * imgb->h[0]* 3 >> 1;
+       evaspixmapsink->evas_pixmap_buf->size = MIN(outsize, evaspixmapsink->evas_pixmap_buf->size);
+
+       GST_DEBUG("End");
+}
+
+static GstFlowReturn
+gst_evaspixmapsink_show_frame (GstVideoSink *vsink, GstBuffer *buf)
+{
+       GstEvasPixmapSink *evaspixmapsink;
+       XV_DATA_PTR img_data = NULL;
+       SCMN_IMGB *scmn_imgb = NULL;
+       gint format = 0;
+
+       evaspixmapsink = GST_EVASPIXMAPSINK (vsink);
+
+       if (GST_STATE(evaspixmapsink) < GST_STATE_PLAYING || log_warn_count < 20) {
+               GST_WARNING_OBJECT (evaspixmapsink, "enter >>>" );
+       }
+
+       if( evaspixmapsink->stop_video ) {
+               GST_INFO_OBJECT (evaspixmapsink, "Stop video is TRUE. so skip show frame..." );
+               goto skip_frame;
+       }
+
+       if (!evaspixmapsink->evas_pixmap_buf) {
+               GST_DEBUG_OBJECT (evaspixmapsink,"creating our evaspixmap buffer");
+               format = gst_evaspixmapsink_get_format_from_caps(evaspixmapsink, GST_BUFFER_CAPS(buf));
+               switch (format) {
+               case GST_MAKE_FOURCC('S', 'T', '1', '2'):
+               case GST_MAKE_FOURCC('S', 'N', '1', '2'):
+               case GST_MAKE_FOURCC('S', '4', '2', '0'):
+               case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
+               case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
+               case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
+               case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
+               case GST_MAKE_FOURCC('S', 'R', '3', '2'):
+                       scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
+                       if(scmn_imgb == NULL) {
+                               GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
+                               goto skip_frame;
+                       }
+                        /* skip buffer if aligned size is smaller than size of caps */
+                       if (scmn_imgb->s[0] < evaspixmapsink->video_width || scmn_imgb->e[0] < evaspixmapsink->video_height) {
+                               GST_WARNING_OBJECT (evaspixmapsink,"invalid size[caps:%dx%d,aligned:%dx%d]. Skip this buffer...",
+                                               evaspixmapsink->video_width, evaspixmapsink->video_height, scmn_imgb->s[0], scmn_imgb->e[0]);
+                               goto skip_frame;
+                       }
+                       evaspixmapsink->aligned_width = scmn_imgb->s[0];
+                       evaspixmapsink->aligned_height = scmn_imgb->e[0];
+                       GST_DEBUG_OBJECT (evaspixmapsink,"video width,height[%dx%d]",evaspixmapsink->video_width, evaspixmapsink->video_height);
+                       GST_INFO_OBJECT (evaspixmapsink,"Use aligned width,height[%dx%d]",evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
+                       break;
+               default:
+                       GST_INFO_OBJECT (evaspixmapsink,"Use original width,height of caps");
+                       break;
+               }
+               evaspixmapsink->evas_pixmap_buf = gst_evaspixmap_buffer_new (evaspixmapsink, GST_BUFFER_CAPS (buf));
+               if (!evaspixmapsink->evas_pixmap_buf) {
+                       /* The create method should have posted an informative error */
+                       goto no_image;
+               }
+               if (evaspixmapsink->evas_pixmap_buf->size < GST_BUFFER_SIZE (buf)) {
+                       GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Failed to create output image buffer of %dx%d pixels",    evaspixmapsink->evas_pixmap_buf->width, evaspixmapsink->evas_pixmap_buf->height),("XServer allocated buffer size did not match input buffer"));
+                       gst_evaspixmap_buffer_destroy (evaspixmapsink->evas_pixmap_buf);
+                       evaspixmapsink->evas_pixmap_buf = NULL;
+                       goto no_image;
+               }
+       }
+
+       switch (evaspixmapsink->evas_pixmap_buf->im_format) {
+       /* Cases for specified formats of Samsung extension */
+       case GST_MAKE_FOURCC('S', 'T', '1', '2'):
+       case GST_MAKE_FOURCC('S', 'N', '1', '2'):
+       case GST_MAKE_FOURCC('S', '4', '2', '0'):
+       case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
+       case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
+       case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
+       case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
+       case GST_MAKE_FOURCC('S', 'R', '3', '2'):
+       {
+               GST_DEBUG_OBJECT (evaspixmapsink,"Samsung extension display format activated. fourcc:%d", evaspixmapsink->evas_pixmap_buf->im_format);
+
+               if (evaspixmapsink->evas_pixmap_buf->xvimage->data) {
+                       img_data = (XV_DATA_PTR) evaspixmapsink->evas_pixmap_buf->xvimage->data;
+                       XV_INIT_DATA(img_data);
+                       scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
+                       if (scmn_imgb == NULL) {
+                               GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
+                               goto skip_frame;
+                       }
+
+                       if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_PADDR) {
+                               img_data->YBuf = (unsigned int)scmn_imgb->p[0];
+                               img_data->CbBuf = (unsigned int)scmn_imgb->p[1];
+                               img_data->CrBuf = (unsigned int)scmn_imgb->p[2];
+                               img_data->BufType = XV_BUF_TYPE_LEGACY;
+
+                       } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_FD) {
+                               /* set gem information to gem_info structure of handle and convert dma-buf fd into drm gem name  */
+                               img_data->YBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[0]);
+                               img_data->CbBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[1]);
+                               img_data->CrBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[2]);
+                               img_data->BufType = XV_BUF_TYPE_DMABUF;
+                               if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_FD) {
+                                       evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_FD;
+                                       GST_WARNING_OBJECT (evaspixmapsink, "BUF SHARED TYPE : FD");
+                               }
+
+                       } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_TIZEN_BUFFER) {
+                               img_data->bo[0] = scmn_imgb->bo[0];
+                               img_data->bo[1] = scmn_imgb->bo[1];
+                               img_data->bo[2] = scmn_imgb->bo[2];
+                               GST_DEBUG("TBM bo %p %p %p", img_data->bo[0], img_data->bo[1], img_data->bo[2]);
+                               /* export bo */
+                               if (img_data->bo[0]) {
+                                       img_data->YBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[0]);
+                               }
+                               if (img_data->bo[1]) {
+                                       img_data->CbBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[1]);
+                               }
+                               if (img_data->bo[2]) {
+                                       img_data->CrBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[2]);
+                               }
+                               if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_TIZEN_BUFFER) {
+                                       evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_TIZEN_BUFFER;
+                                       GST_WARNING_OBJECT (evaspixmapsink, "BUF SHARED TYPE : TIZEN BUFFER");
+                               }
+                       } else {
+                               GST_WARNING_OBJECT (evaspixmapsink, "Not supported, buf_share_method(%d)", scmn_imgb->buf_share_method);
+                               goto skip_frame;
+                       }
+                       if (!img_data->YBuf) {
+                               GST_WARNING_OBJECT (evaspixmapsink, "img_data->YBuf is NULL. skip buffer put..." );
+                               goto skip_frame;
+                       }
+                       GST_LOG_OBJECT(evaspixmapsink, "YBuf[%d], CbBuf[%d], CrBuf[%d]",
+                                       img_data->YBuf, img_data->CbBuf, img_data->CrBuf );
+               } else {
+                       GST_WARNING_OBJECT (evaspixmapsink, "xvimage->data is NULL. skip buffer put..." );
+                       goto skip_frame;
+               }
+               break;
+       }
+       default:
+       {
+               if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_NONE) {
+                       evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_NONE;
+               }
+               GST_DEBUG_OBJECT (evaspixmapsink,"Normal format activated. fourcc = %d", evaspixmapsink->evas_pixmap_buf->im_format);
+               if(evaspixmapsink->need_combine_data == 1)
+               {
+                       gst_evaspixmapsink_combine_i420_scmn_data(evaspixmapsink, buf);
+               }
+               else
+               {
+                       memcpy (evaspixmapsink->evas_pixmap_buf->xvimage->data,
+                       GST_BUFFER_DATA (buf),
+                       MIN (GST_BUFFER_SIZE (buf), evaspixmapsink->evas_pixmap_buf->size));
+               }
+               break;
+       }
+       }
+       gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
+
+skip_frame:
+
+       if (GST_STATE(evaspixmapsink) < GST_STATE_PLAYING || log_warn_count < 20) {
+               GST_WARNING_OBJECT (evaspixmapsink, "leave <<<" );
+       }
+
+       return GST_FLOW_OK;
+
+       /* ERRORS */
+       no_image:
+       {
+               /* No image available. That's very bad ! */
+               GST_WARNING_OBJECT (evaspixmapsink,"could not create image");
+               return GST_FLOW_ERROR;
+       }
+}
+
+static gboolean
+gst_evaspixmapsink_event (GstBaseSink *sink, GstEvent *event)
+{
+       GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (sink);
+
+       switch (GST_EVENT_TYPE (event)) {
+       case GST_EVENT_FLUSH_START:
+               GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_START");
+               break;
+       case GST_EVENT_FLUSH_STOP:
+               GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_STOP");
+               break;
+       default:
+               break;
+       }
+       if (GST_BASE_SINK_CLASS (parent_class)->event) {
+               return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
+       } else {
+               return TRUE;
+       }
+}
+
+/* Interfaces stuff */
+
+static gboolean
+gst_evaspixmapsink_interface_supported (GstImplementsInterface *iface, GType type)
+{
+  g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE);
+  return TRUE;
+}
+
+static void
+gst_evaspixmapsink_interface_init (GstImplementsInterfaceClass *klass)
+{
+  klass->supported = gst_evaspixmapsink_interface_supported;
+}
+
+static void
+gst_evaspixmapsink_navigation_send_event (GstNavigation *navigation, GstStructure *structure)
+{
+  GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (navigation);
+  GstPad *peer;
+  int i = 0;
+
+  if ((peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (evaspixmapsink)))) {
+    GstEvent *event;
+    GstVideoRectangle result;
+    gdouble x, y, xscale = 1.0, yscale = 1.0;
+
+    event = gst_event_new_navigation (structure);
+
+    /* We take the flow_lock while we look at the window */
+    g_mutex_lock (evaspixmapsink->flow_lock);
+
+    for (i = 0; i < evaspixmapsink->num_of_pixmaps; i ++) {
+      if (!evaspixmapsink->xpixmap[i]) {
+        g_mutex_unlock (evaspixmapsink->flow_lock);
+        return;
+      }
+    }
+
+    memcpy (&result, &evaspixmapsink->render_rect, sizeof (GstVideoRectangle));
+
+    g_mutex_unlock (evaspixmapsink->flow_lock);
+
+    /* We calculate scaling using the original video frames geometry to include
+       pixel aspect ratio scaling. */
+    xscale = (gdouble) evaspixmapsink->video_width / result.w;
+    yscale = (gdouble) evaspixmapsink->video_height / result.h;
+
+    /* Converting pointer coordinates to the non scaled geometry */
+    if (gst_structure_get_double (structure, "pointer_x", &x)) {
+      x = MIN (x, result.x + result.w);
+      x = MAX (x - result.x, 0);
+      gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
+          (gdouble) x * xscale, NULL);
+    }
+    if (gst_structure_get_double (structure, "pointer_y", &y)) {
+      y = MIN (y, result.y + result.h);
+      y = MAX (y - result.y, 0);
+      gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
+          (gdouble) y * yscale, NULL);
+    }
+
+    gst_pad_send_event (peer, event);
+    gst_object_unref (peer);
+  }
+}
+
+static void
+gst_evaspixmapsink_navigation_init (GstNavigationInterface *iface)
+{
+  iface->send_event = gst_evaspixmapsink_navigation_send_event;
+}
+
+static const GList*
+gst_evaspixmapsink_colorbalance_list_channels (GstColorBalance *balance)
+{
+  GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
+
+  g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
+
+  if (evaspixmapsink->xcontext)
+    return evaspixmapsink->xcontext->channels_list;
+  else
+    return NULL;
+}
+
+static void
+gst_evaspixmapsink_colorbalance_set_value (GstColorBalance *balance, GstColorBalanceChannel *channel, gint value)
+{
+  GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
+
+  g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
+  g_return_if_fail (channel->label != NULL);
+
+  evaspixmapsink->cb_changed = TRUE;
+
+  /* Normalize val to [-1000, 1000] */
+  value = floor (0.5 + -1000 + 2000 * (value - channel->min_value) /
+      (double) (channel->max_value - channel->min_value));
+
+  if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
+    evaspixmapsink->hue = value;
+  } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
+    evaspixmapsink->saturation = value;
+  } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
+    evaspixmapsink->contrast = value;
+  } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
+    evaspixmapsink->brightness = value;
+  } else {
+    g_warning ("got an unknown channel %s", channel->label);
+    return;
+  }
+
+  gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
+}
+
+static gint
+gst_evaspixmapsink_colorbalance_get_value (GstColorBalance *balance, GstColorBalanceChannel *channel)
+{
+  GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
+  gint value = 0;
+
+  g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
+  g_return_val_if_fail (channel->label != NULL, 0);
+
+  if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
+    value = evaspixmapsink->hue;
+  } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
+    value = evaspixmapsink->saturation;
+  } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
+    value = evaspixmapsink->contrast;
+  } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
+    value = evaspixmapsink->brightness;
+  } else {
+    g_warning ("got an unknown channel %s", channel->label);
+  }
+
+  /* Normalize val to [channel->min_value, channel->max_value] */
+  value = channel->min_value + (channel->max_value - channel->min_value) * (value + 1000) / 2000;
+
+  return value;
+}
+
+static void
+gst_evaspixmapsink_colorbalance_init (GstColorBalanceClass *iface)
+{
+  GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE;
+  iface->list_channels = gst_evaspixmapsink_colorbalance_list_channels;
+  iface->set_value = gst_evaspixmapsink_colorbalance_set_value;
+  iface->get_value = gst_evaspixmapsink_colorbalance_get_value;
+}
+
+static const GList *
+gst_evaspixmapsink_probe_get_properties (GstPropertyProbe *probe)
+{
+       GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
+       static GList *list = NULL;
+
+       if (!list) {
+               list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
+               list = g_list_append (list, g_object_class_find_property (klass, "autopaint-colorkey"));
+               list = g_list_append (list, g_object_class_find_property (klass, "double-buffer"));
+               list = g_list_append (list, g_object_class_find_property (klass, "colorkey"));
+       }
+
+       return list;
+}
+
+static void
+gst_evaspixmapsink_probe_probe_property (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
+{
+  GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
+
+  switch (prop_id) {
+    case PROP_DEVICE:
+    case PROP_AUTOPAINT_COLORKEY:
+    case PROP_DOUBLE_BUFFER:
+    case PROP_COLORKEY:
+      GST_DEBUG_OBJECT (evaspixmapsink,"probing device list and get capabilities");
+      if (!evaspixmapsink->xcontext) {
+        GST_DEBUG_OBJECT (evaspixmapsink,"generating xcontext");
+        evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
+        if (!evaspixmapsink->xcontext) {
+          GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
+        }
+      }
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+gst_evaspixmapsink_probe_needs_probe (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
+{
+  GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
+  gboolean ret = FALSE;
+
+  switch (prop_id) {
+    case PROP_DEVICE:
+    case PROP_AUTOPAINT_COLORKEY:
+    case PROP_DOUBLE_BUFFER:
+    case PROP_COLORKEY:
+      if (evaspixmapsink->xcontext != NULL) {
+        ret = FALSE;
+      } else {
+        ret = TRUE;
+      }
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
+      break;
+  }
+
+  return ret;
+}
+
+static GValueArray *
+gst_evaspixmapsink_probe_get_values (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
+{
+  GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
+  GValueArray *array = NULL;
+
+  if (G_UNLIKELY (!evaspixmapsink->xcontext)) {
+    GST_WARNING_OBJECT (evaspixmapsink,"we don't have any xcontext, can't "
+        "get values");
+    goto beach;
+  }
+
+  switch (prop_id) {
+    case PROP_DEVICE:
+    {
+      guint i;
+      GValue value = { 0 };
+
+      array = g_value_array_new (evaspixmapsink->xcontext->nb_adaptors);
+      g_value_init (&value, G_TYPE_STRING);
+
+      for (i = 0; i < evaspixmapsink->xcontext->nb_adaptors; i++) {
+        gchar *adaptor_id_s = g_strdup_printf ("%u", i);
+
+        g_value_set_string (&value, adaptor_id_s);
+        g_value_array_append (array, &value);
+        g_free (adaptor_id_s);
+      }
+      g_value_unset (&value);
+      break;
+    }
+    case PROP_AUTOPAINT_COLORKEY:
+      if (evaspixmapsink->have_autopaint_colorkey) {
+        GValue value = { 0 };
+
+        array = g_value_array_new (2);
+        g_value_init (&value, G_TYPE_BOOLEAN);
+        g_value_set_boolean (&value, FALSE);
+        g_value_array_append (array, &value);
+        g_value_set_boolean (&value, TRUE);
+        g_value_array_append (array, &value);
+        g_value_unset (&value);
+      }
+      break;
+    case PROP_DOUBLE_BUFFER:
+      if (evaspixmapsink->have_double_buffer) {
+        GValue value = { 0 };
+
+        array = g_value_array_new (2);
+        g_value_init (&value, G_TYPE_BOOLEAN);
+        g_value_set_boolean (&value, FALSE);
+        g_value_array_append (array, &value);
+        g_value_set_boolean (&value, TRUE);
+        g_value_array_append (array, &value);
+        g_value_unset (&value);
+      }
+      break;
+    case PROP_COLORKEY:
+      if (evaspixmapsink->have_colorkey) {
+        GValue value = { 0 };
+
+        array = g_value_array_new (1);
+        g_value_init (&value, GST_TYPE_INT_RANGE);
+        gst_value_set_int_range (&value, 0, 0xffffff);
+        g_value_array_append (array, &value);
+        g_value_unset (&value);
+      }
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
+      break;
+  }
+
+beach:
+  return array;
+}
+
+static void
+gst_evaspixmapsink_property_probe_interface_init (GstPropertyProbeInterface *iface)
+{
+       iface->get_properties = gst_evaspixmapsink_probe_get_properties;
+       iface->probe_property = gst_evaspixmapsink_probe_probe_property;
+       iface->needs_probe = gst_evaspixmapsink_probe_needs_probe;
+       iface->get_values = gst_evaspixmapsink_probe_get_values;
+}
+
+static gboolean
+gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink)
+{
+       Display *dpy;
+       Pixmap *pixmap_id[NUM_OF_PIXMAP];
+       int evas_object_width = 0;
+       int evas_object_height = 0;
+       int pixmap_width = 0;
+       int pixmap_height = 0;
+       unsigned int xw = 0;
+       unsigned int xh = 0;
+       int i = 0;
+       XGCValues gc_values_black;
+       gc_values_black.foreground = 0xff000000;
+#ifdef DUMP_IMG
+  int ret = 0;
+  char file_name[128];
+  char *dump_data;
+  int dump_w = 0;
+#endif
+
+       GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
+
+       if (!evaspixmapsink) {
+               GST_ERROR_OBJECT (evaspixmapsink,"could not get evaspixmapsink..");
+               return FALSE;
+       }
+       g_mutex_lock (evaspixmapsink->flow_lock);
+
+       /* Set xcontext and display */
+       if (!evaspixmapsink->xcontext) {
+               GST_WARNING_OBJECT (evaspixmapsink,"there's no xcontext, try to get one..");
+               evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
+               if (!evaspixmapsink->xcontext) {
+                       GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
+                       g_mutex_unlock (evaspixmapsink->flow_lock);
+                       return FALSE;
+               }
+       }
+
+       /* Set evas image object size */
+       evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evas_object_width, &evas_object_height);
+
+       /* check if it is redundant request */
+       for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+               if (evaspixmapsink->xpixmap[i]) {
+                       if (!evaspixmapsink->use_origin_size && evaspixmapsink->xpixmap[i]->width && evaspixmapsink->xpixmap[i]->height) {
+                               if (evaspixmapsink->xpixmap[i]->width == evas_object_width && evaspixmapsink->xpixmap[i]->height == evas_object_height) {
+                                       GST_WARNING_OBJECT (evaspixmapsink,"pixmap was already created(w:%d, h:%d), skip it..",
+                                               evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
+                                       if (evaspixmapsink->need_to_fill_black) {
+                                               for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+                                                       g_mutex_lock (evaspixmapsink->x_lock);
+                                                       XFillRectangle (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc,
+                                                               0, 0, evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
+                                                       GST_LOG_OBJECT (evaspixmapsink,"fill black to xpixmap[%d] with size(w:%d,h:%d)", evaspixmapsink->xpixmap[i]->pixmap,
+                                                                       evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
+#ifdef DUMP_IMG
+              dump_w = evaspixmapsink->xpixmap[i]->width + (32 - (evaspixmapsink->xpixmap[i]->width%32)); // for multiples of 32
+              if(g_cnt<100)
+              {
+                evaspixmapsink->pixmap_addr[i] = gst_evaspixmapsink_get_buffer(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, dump_w, evaspixmapsink->xpixmap[i]->height, i);
+                GST_ERROR("<DUMP_%2.2d> pixmap[%d] addr %p (w : %d, h : %d)", g_cnt, i, evaspixmapsink->pixmap_addr[i], dump_w, evaspixmapsink->xpixmap[i]->height);
+                sprintf(file_name, "/opt/usr/media/DUMP_%2.2d.dump", g_cnt);
+
+                dump_data = g_malloc(dump_w * evaspixmapsink->xpixmap[i]->height * 4);
+                memcpy (dump_data, evaspixmapsink->pixmap_addr[i], dump_w * evaspixmapsink->xpixmap[i]->height * 4);
+
+                ret = util_write_rawdata(file_name, dump_data, dump_w * evaspixmapsink->xpixmap[i]->height * 4);
+                if (ret) {
+                  GST_ERROR_OBJECT (evaspixmapsink, "util_write_rawdata() failed");
+                }
+                else
+                  g_cnt++;
+                g_free(dump_data);
+
+                if (g_bufinfo[i]) {
+                  gst_evaspixmapsink_free_buffer (i);
+                  g_bufinfo[i] = NULL;
+                }
+                evaspixmapsink->pixmap_addr[i] = NULL;
+              }
+#endif
+                                                       g_mutex_unlock (evaspixmapsink->x_lock);
+                                               }
+                                               evaspixmapsink->need_to_fill_black = FALSE;
+                                       }
+                                       goto SKIP_LINK;
+                               }
+                       }
+               }
+       }
+
+       dpy = evaspixmapsink->xcontext->disp;
+
+       if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
+               pixmap_width = evaspixmapsink->video_width;
+               pixmap_height = evaspixmapsink->video_height;
+               GST_INFO_OBJECT (evaspixmapsink,"set size to media src size(%dx%d)", pixmap_width, pixmap_height);
+       }
+
+       g_mutex_lock (evaspixmapsink->x_lock);
+       evaspixmapsink->sizediff_width = 0;
+       evaspixmapsink->sizediff_height = 0;
+       if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
+               XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, pixmap_width, pixmap_height, &xw, &xh);
+               if (!evas_object_width || !evas_object_height) {
+                       evaspixmapsink->w = xw;
+                       evaspixmapsink->h = xh;
+               } else {
+                       evaspixmapsink->w = evas_object_width;
+                       evaspixmapsink->h = evas_object_height;
+               }
+               GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, pixmap_width, pixmap_height, xw, xh);
+       } else {
+               XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, evas_object_width, evas_object_height, &xw, &xh);
+               GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, evas_object_width, evas_object_height, xw, xh);
+               evaspixmapsink->w = xw;
+               evaspixmapsink->h = xh;
+               /* update difference of size information (between evas image object's and pixmap's) */
+               evaspixmapsink->sizediff_width = xw - evas_object_width;
+               evaspixmapsink->sizediff_height = xh - evas_object_height;
+       }
+
+       /* create xpixmap structure */
+       for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+               if (!evaspixmapsink->xpixmap[i]) {
+                       /* xpixmap can be created in this function only */
+                       evaspixmapsink->xpixmap[i] = g_new0 (GstXPixmap, 1);
+                       if(!evaspixmapsink->xpixmap[i]) {
+                               GST_ERROR_OBJECT (evaspixmapsink,"xpixmap is not valid..");
+                               int j = 0;
+                               for (j = 0; j < i; j++) {
+                                       g_free(evaspixmapsink->xpixmap[j]);
+                               }
+                               goto GO_OUT_OF_FUNC;
+                       }
+               }
+       }
+
+       /* create pixmap */
+       if (!xw || !xh) {
+               GST_WARNING_OBJECT (evaspixmapsink,"skip creating pixmap..xw(%d),xh(%d)",xw,xh);
+               goto GO_OUT_OF_FUNC;
+       } else {
+               /* multiple pixmaps creation */
+               for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+                       pixmap_id[i] = XCreatePixmap(dpy, DefaultRootWindow(dpy), xw, xh, DefaultDepth(dpy, DefaultScreen(dpy)));
+                       if ( (int)pixmap_id[i] == BadAlloc || (int)pixmap_id[i] == BadDrawable || (int)pixmap_id[i] == BadValue ) {
+                               GST_ERROR_OBJECT (evaspixmapsink,"pixmap[%d] allocation error..", i);
+                               int j = 0;
+                               for (j = 0; j < i; j++) {
+                                       XFreePixmap(dpy, pixmap_id[j]);
+                               }
+                               goto GO_OUT_OF_FUNC;
+                       }
+                       evaspixmapsink->need_to_fill_black = FALSE;
+                       GST_INFO_OBJECT (evaspixmapsink,"creation pixmap_id[%d]:%d success", i, pixmap_id[i]);
+                       GST_DEBUG_OBJECT (evaspixmapsink,"evas_object_width(%d),evas_object_height(%d),pixmap:%d,depth:%d",
+                                                               evas_object_width,evas_object_height,pixmap_id[i],DefaultDepth(dpy, DefaultScreen(dpy)));
+               }
+       }
+
+       for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+               if (evaspixmapsink->xpixmap[i]->pixmap && pixmap_id[i] != evaspixmapsink->xpixmap[i]->pixmap) {
+                       g_mutex_unlock (evaspixmapsink->x_lock);
+                       g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
+
+                       /* If we reset another pixmap, do below */
+                       if (evaspixmapsink->xpixmap[i]->prev_pixmap) {
+                               GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d), gc(%x), destroy previous damage(%d)",
+                                               evaspixmapsink->xpixmap[i]->prev_pixmap, evaspixmapsink->xpixmap[i]->prev_gc, evaspixmapsink->prev_damage[i]);
+                               g_mutex_lock (evaspixmapsink->x_lock);
+                               XFreePixmap(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_pixmap);
+                               XFreeGC (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_gc);
+                               XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->prev_damage[i]);
+                               XSync(evaspixmapsink->xcontext->disp, FALSE);
+                               g_mutex_unlock (evaspixmapsink->x_lock);
+                               evaspixmapsink->prev_damage[i] = NULL;
+                       }
+                       evaspixmapsink->xpixmap[i]->prev_pixmap = evaspixmapsink->xpixmap[i]->pixmap;
+                       evaspixmapsink->xpixmap[i]->prev_gc = evaspixmapsink->xpixmap[i]->gc;
+                       evaspixmapsink->xpixmap[i]->pixmap = 0;
+                       evaspixmapsink->xpixmap[i]->ref = 0;
+                       evaspixmapsink->xpixmap[i]->damaged_time = 0;
+
+                       g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
+                       g_mutex_lock (evaspixmapsink->x_lock);
+               }
+       }
+
+       for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+               /* Set pixmap id and create GC */
+               evaspixmapsink->xpixmap[i]->pixmap = pixmap_id[i];
+               evaspixmapsink->xpixmap[i]->gc = XCreateGC(dpy, evaspixmapsink->xpixmap[i]->pixmap, GCForeground, &gc_values_black);
+               evaspixmapsink->xpixmap[i]->width = xw;
+               evaspixmapsink->xpixmap[i]->height = xh;
+
+               /* Create XDamage */
+               if (evaspixmapsink->damage[i]) {
+                       evaspixmapsink->prev_damage[i] = evaspixmapsink->damage[i];
+               }
+               evaspixmapsink->damage[i] = XDamageCreate (dpy, evaspixmapsink->xpixmap[i]->pixmap, XDamageReportRawRectangles);
+
+               GST_WARNING_OBJECT (evaspixmapsink,"xpixmap[%d]->(pixmap:%d,gc:%p), damage[%d]:%d",
+                                       i, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc, i, evaspixmapsink->damage[i]);
+
+               /* Fill blackcolor for the new pixmap */
+               XFillRectangle (evaspixmapsink->xcontext->disp, pixmap_id[i], evaspixmapsink->xpixmap[i]->gc,
+                                       0, 0, evaspixmapsink->w, evaspixmapsink->h);
+               GST_LOG_OBJECT (evaspixmapsink,"fill black to xpixmap[%d] with size(w:%d,h:%d)", pixmap_id[i],
+                                       evaspixmapsink->w, evaspixmapsink->h);
+
+#ifdef DUMP_IMG
+    dump_w = evaspixmapsink->w + (32 - (evaspixmapsink->w%32)); // for multiples of 32
+    if(g_cnt<100)
+    {
+      evaspixmapsink->pixmap_addr[i] = gst_evaspixmapsink_get_buffer(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, dump_w, evaspixmapsink->h, i);
+      GST_ERROR("<DUMP_%2.2d> pixmap[%d] addr %p (w : %d, h : %d)", g_cnt, i, evaspixmapsink->pixmap_addr[i], dump_w, evaspixmapsink->h);
+      sprintf(file_name, "/opt/usr/media/DUMP_%2.2d.dump", g_cnt);
+
+      dump_data = g_malloc(dump_w * evaspixmapsink->h * 4);
+      memcpy (dump_data, evaspixmapsink->pixmap_addr[i], dump_w * evaspixmapsink->h * 4);
+
+      ret = util_write_rawdata(file_name, dump_data, dump_w * evaspixmapsink->h * 4);
+      if (ret) {
+        GST_ERROR_OBJECT (evaspixmapsink, "util_write_rawdata() failed");
+      }
+      else
+        g_cnt++;
+      g_free(dump_data);
+
+      if (g_bufinfo[i]) {
+        gst_evaspixmapsink_free_buffer (i);
+        g_bufinfo[i] = NULL;
+      }
+      evaspixmapsink->pixmap_addr[i] = NULL;
+    }
+#endif
+       }
+
+       XSync(dpy, FALSE);
+
+       /* Set flag for mapping evas object with xpixmap */
+       evaspixmapsink->do_link = TRUE;
+       if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
+               GST_WARNING_OBJECT (evaspixmapsink,"epipe_request_count(%d), skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
+       } else {
+               ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink));
+               evaspixmapsink->epipe_request_count++;
+       }
+
+       gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
+
+       g_mutex_unlock (evaspixmapsink->x_lock);
+
+
+SKIP_LINK:
+       g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
+       evaspixmapsink->last_updated_idx = -1;
+       g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
+
+       g_mutex_unlock (evaspixmapsink->flow_lock);
+
+       GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
+
+       return TRUE;
+
+GO_OUT_OF_FUNC:
+       g_mutex_unlock (evaspixmapsink->x_lock);
+       g_mutex_unlock (evaspixmapsink->flow_lock);
+       return FALSE;
+}
+
+static void
+gst_evaspixmapsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+       GstEvasPixmapSink *evaspixmapsink;
+       g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
+       evaspixmapsink = GST_EVASPIXMAPSINK (object);
+
+       switch (prop_id) {
+       case PROP_HUE:
+               evaspixmapsink->hue = g_value_get_int (value);
+               evaspixmapsink->cb_changed = TRUE;
+               gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
+               break;
+       case PROP_CONTRAST:
+               evaspixmapsink->contrast = g_value_get_int (value);
+               evaspixmapsink->cb_changed = TRUE;
+               gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
+               break;
+       case PROP_BRIGHTNESS:
+               evaspixmapsink->brightness = g_value_get_int (value);
+               evaspixmapsink->cb_changed = TRUE;
+               gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
+               break;
+       case PROP_SATURATION:
+               evaspixmapsink->saturation = g_value_get_int (value);
+               evaspixmapsink->cb_changed = TRUE;
+               gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
+               break;
+       case PROP_DISPLAY:
+               evaspixmapsink->display_name = g_strdup (g_value_get_string (value));
+               break;
+       case PROP_SYNCHRONOUS:
+               evaspixmapsink->synchronous = g_value_get_boolean (value);
+               if (evaspixmapsink->xcontext) {
+                       g_mutex_lock (evaspixmapsink->x_lock);
+                       XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
+                       g_mutex_unlock (evaspixmapsink->x_lock);
+                       GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
+               }
+               break;
+       case PROP_PIXEL_ASPECT_RATIO:
+               g_free (evaspixmapsink->par);
+               evaspixmapsink->par = g_new0 (GValue, 1);
+               g_value_init (evaspixmapsink->par, GST_TYPE_FRACTION);
+               if (!g_value_transform (value, evaspixmapsink->par)) {
+                       g_warning ("Could not transform string to aspect ratio");
+                       gst_value_set_fraction (evaspixmapsink->par, 1, 1);
+               }
+               GST_DEBUG_OBJECT (evaspixmapsink,"set PAR to %d/%d", gst_value_get_fraction_numerator (evaspixmapsink->par), gst_value_get_fraction_denominator (evaspixmapsink->par));
+               break;
+       case PROP_DEVICE:
+               evaspixmapsink->adaptor_no = atoi (g_value_get_string (value));
+               break;
+       case PROP_DOUBLE_BUFFER:
+               evaspixmapsink->double_buffer = g_value_get_boolean (value);
+               break;
+       case PROP_AUTOPAINT_COLORKEY:
+               evaspixmapsink->autopaint_colorkey = g_value_get_boolean (value);
+               break;
+       case PROP_COLORKEY:
+               evaspixmapsink->colorkey = g_value_get_int (value);
+               break;
+       case PROP_PIXMAP_WIDTH:
+       {
+               /* To do : code related to pixmap re-link */
+               GST_LOG_OBJECT (evaspixmapsink, "Not supported");
+               break;
+       }
+       case PROP_PIXMAP_HEIGHT:
+       {
+               /* To do : code related to pixmap re-link */
+               GST_LOG_OBJECT (evaspixmapsink, "Not supported");
+               break;
+       }
+       case PROP_DISPLAY_GEOMETRY_METHOD:
+       {
+               guint new_val = g_value_get_enum (value);
+               if (evaspixmapsink->display_geometry_method != new_val) {
+                       evaspixmapsink->display_geometry_method = new_val;
+                       GST_INFO_OBJECT (evaspixmapsink,"Overlay geometry method update, display_geometry_method(%d)",evaspixmapsink->display_geometry_method);
+                       if( evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_FULL_SCREEN &&
+                                 evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_CROPPED_FULL_SCREEN ) {
+                               if( evaspixmapsink->xcontext ) {
+                                       g_mutex_lock( evaspixmapsink->flow_lock );
+                                       int i = 0;
+                                       for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+                                               if (evaspixmapsink->xpixmap[i]) {
+                                                       gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
+                                               }
+                                       }
+                                       g_mutex_unlock( evaspixmapsink->flow_lock );
+                               }
+                       }
+                       if (evaspixmapsink->xcontext) {
+                               gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
+                       }
+               }
+               break;
+       }
+       case PROP_DST_ROI_X:
+               evaspixmapsink->dst_roi.x = g_value_get_int (value);
+               GST_INFO_OBJECT (evaspixmapsink, "ROI_X(%d)",evaspixmapsink->dst_roi.x );
+               break;
+       case PROP_DST_ROI_Y:
+               evaspixmapsink->dst_roi.y = g_value_get_int (value);
+               GST_INFO_OBJECT (evaspixmapsink, "ROI_Y(%d)",evaspixmapsink->dst_roi.y );
+               break;
+       case PROP_DST_ROI_W:
+               evaspixmapsink->dst_roi.w = g_value_get_int (value);
+               GST_INFO_OBJECT (evaspixmapsink, "ROI_W(%d)",evaspixmapsink->dst_roi.w );
+               break;
+       case PROP_DST_ROI_H:
+               evaspixmapsink->dst_roi.h = g_value_get_int (value);
+               GST_INFO_OBJECT (evaspixmapsink, "ROI_H(%d)",evaspixmapsink->dst_roi.h );
+               break;
+       case PROP_STOP_VIDEO:
+               evaspixmapsink->stop_video = g_value_get_int (value);
+               g_mutex_lock( evaspixmapsink->flow_lock );
+               if( evaspixmapsink->stop_video ) {
+                       GST_INFO_OBJECT (evaspixmapsink, "XPixmap CLEAR when set video-stop property" );
+                       int i = 0;
+                       for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+                               if (evaspixmapsink->xpixmap[i]) {
+                                       gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
+                               }
+                       }
+               }
+               GST_INFO_OBJECT (evaspixmapsink, "video-stop property(%d)", evaspixmapsink->stop_video);
+
+               g_mutex_unlock( evaspixmapsink->flow_lock );
+               break;
+       case PROP_EVAS_OBJECT:
+       {
+               Evas_Object *eo = g_value_get_pointer (value);
+               if ( is_evas_image_object (eo)) {
+                       if (!evaspixmapsink->epipe) {
+                               evaspixmapsink->epipe = ecore_pipe_add (ecore_pipe_callback_handler, evaspixmapsink);
+                               if (!evaspixmapsink->epipe) {
+                                       GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: ecore_pipe_add() failed");
+                                       break;
+                               }
+                       }
+                       if (evaspixmapsink->eo == NULL) {
+                               evaspixmapsink->eo = eo;
+                               /* add evas object callbacks on a new evas image object */
+                               EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK (eo, evaspixmapsink);
+                               if (GST_STATE(evaspixmapsink) < GST_STATE_PAUSED) {
+                                       GST_INFO_OBJECT (evaspixmapsink,"It's the first time the new evas image object(%x) is set, skip gst_evaspixmapsink_xpixmap_link()..", eo);
+                                       break;
+                               } else {
+                                       if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
+                                               GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
+                                               evaspixmapsink->eo = NULL;
+                                               break;
+                                       }
+                               }
+                       }
+                       if (eo == evaspixmapsink->eo) {
+                               GST_LOG_OBJECT (evaspixmapsink,"new evas image object(%x) is same as the previous one(%x)", eo, evaspixmapsink->eo);
+                       } else {
+                               GST_INFO_OBJECT (evaspixmapsink,"new evas image object(%x), previous one(%x)", eo, evaspixmapsink->eo);
+                               /* delete evas object callbacks registrated on a former evas image object */
+                               EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (evaspixmapsink->eo);
+                               evaspixmapsink->eo = eo;
+                               if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
+                                       GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
+                                       evaspixmapsink->eo = NULL;
+                                       break;
+                               }
+                               /* add evas object callbacks on a new evas image object */
+                               EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK (eo, evaspixmapsink);
+                       }
+                       GST_INFO_OBJECT (evaspixmapsink,"Evas image object(%x) is set", evaspixmapsink->eo);
+               } else {
+                       GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: value is not an evas image object");
+               }
+               break;
+       }
+       case PROP_FLIP:
+               evaspixmapsink->flip = g_value_get_enum(value);
+               break;
+       case PROP_ROTATE_ANGLE:
+               evaspixmapsink->rotate_angle = g_value_get_enum (value);
+               break;
+       case PROP_VISIBLE:
+       {
+               Eina_Bool r = EINA_FALSE;
+               gboolean visible = g_value_get_boolean (value);
+               GST_INFO_OBJECT (evaspixmapsink,"evaspixmapsink->visible(%d), new value of visible(%d)", evaspixmapsink->visible, visible);
+               if (evaspixmapsink->visible != visible) {
+                       evaspixmapsink->visible = visible;
+                       if (evaspixmapsink->eo) {
+                               evaspixmapsink->update_visibility = UPDATE_TRUE;
+                               if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
+                                       GST_WARNING_OBJECT (evaspixmapsink,"skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
+                                       if (visible) {
+                                               evas_object_show(evaspixmapsink->eo);
+                                               GST_WARNING_OBJECT (evaspixmapsink, "object show (forcely)");
+                                       }
+                               } else {
+                                       r = ecore_pipe_write (evaspixmapsink->epipe, &evaspixmapsink->update_visibility, SIZE_FOR_UPDATE_VISIBILITY);
+                                       if (r == EINA_FALSE)  {
+                                               GST_WARNING ("Failed to ecore_pipe_write() for updating visibility)\n");
+                                       }
+                                       evaspixmapsink->epipe_request_count++;
+                               }
+
+                               if (!visible) {
+                                       int i = 0;
+                                       g_mutex_lock( evaspixmapsink->flow_lock );
+                                       for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+                                               if (evaspixmapsink->xpixmap[i]) {
+                                                       gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
+                                               }
+                                       }
+                                       evas_object_hide(evaspixmapsink->eo);
+                                       GST_INFO_OBJECT (evaspixmapsink, "object hide (forcely)");
+                                       g_mutex_unlock( evaspixmapsink->flow_lock );
+                               } else {
+                                       gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
+                               }
+                       } else {
+                               GST_WARNING_OBJECT (evaspixmapsink,"evas image object was not set");
+                       }
+               }
+               break;
+       }
+       case PROP_ORIGIN_SIZE:
+               evaspixmapsink->use_origin_size = g_value_get_boolean (value);
+               GST_INFO_OBJECT (evaspixmapsink,"set origin-size (%d)",evaspixmapsink->use_origin_size);
+               if (evaspixmapsink->previous_origin_size != evaspixmapsink->use_origin_size) {
+                       if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
+                               GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
+                       }
+                       evaspixmapsink->previous_origin_size = evaspixmapsink->use_origin_size;
+               }
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+gst_evaspixmapsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+       GstEvasPixmapSink *evaspixmapsink;
+
+       g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
+
+       evaspixmapsink = GST_EVASPIXMAPSINK (object);
+
+       switch (prop_id) {
+       case PROP_HUE:
+               g_value_set_int (value, evaspixmapsink->hue);
+               break;
+       case PROP_CONTRAST:
+               g_value_set_int (value, evaspixmapsink->contrast);
+               break;
+       case PROP_BRIGHTNESS:
+               g_value_set_int (value, evaspixmapsink->brightness);
+               break;
+       case PROP_SATURATION:
+               g_value_set_int (value, evaspixmapsink->saturation);
+               break;
+       case PROP_DISPLAY:
+               g_value_set_string (value, evaspixmapsink->display_name);
+               break;
+       case PROP_SYNCHRONOUS:
+               g_value_set_boolean (value, evaspixmapsink->synchronous);
+               break;
+       case PROP_PIXEL_ASPECT_RATIO:
+               if (evaspixmapsink->par) {
+                       if (!g_value_transform (evaspixmapsink->par, value)) {
+                               g_warning ("g_value_transform() failure");
+                       }
+               }
+               break;
+       case PROP_DEVICE:
+       {
+               char *adaptor_no_s = g_strdup_printf ("%u", evaspixmapsink->adaptor_no);
+               g_value_set_string (value, adaptor_no_s);
+               g_free (adaptor_no_s);
+               break;
+       }
+       case PROP_DEVICE_NAME:
+               if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->adaptors) {
+                       g_value_set_string (value,
+                       evaspixmapsink->xcontext->adaptors[evaspixmapsink->adaptor_no]);
+               } else {
+                       g_value_set_string (value, NULL);
+               }
+               break;
+       case PROP_DOUBLE_BUFFER:
+               g_value_set_boolean (value, evaspixmapsink->double_buffer);
+               break;
+       case PROP_AUTOPAINT_COLORKEY:
+               g_value_set_boolean (value, evaspixmapsink->autopaint_colorkey);
+               break;
+       case PROP_COLORKEY:
+               g_value_set_int (value, evaspixmapsink->colorkey);
+               break;
+       case PROP_PIXMAP_WIDTH:
+       {
+               GST_LOG_OBJECT (evaspixmapsink, "Not supported");
+               break;
+       }
+       case PROP_PIXMAP_HEIGHT:
+       {
+               GST_LOG_OBJECT (evaspixmapsink, "Not supported");
+               break;
+       }
+       case PROP_DISPLAY_GEOMETRY_METHOD:
+               g_value_set_enum (value, evaspixmapsink->display_geometry_method);
+               break;
+       case PROP_DST_ROI_X:
+               g_value_set_int (value, evaspixmapsink->dst_roi.x);
+               break;
+       case PROP_DST_ROI_Y:
+               g_value_set_int (value, evaspixmapsink->dst_roi.y);
+               break;
+       case PROP_DST_ROI_W:
+               g_value_set_int (value, evaspixmapsink->dst_roi.w);
+               break;
+       case PROP_DST_ROI_H:
+               g_value_set_int (value, evaspixmapsink->dst_roi.h);
+               break;
+       case PROP_STOP_VIDEO:
+               g_value_set_int (value, evaspixmapsink->stop_video);
+               break;
+       case PROP_EVAS_OBJECT:
+               g_value_set_pointer (value, evaspixmapsink->eo);
+               break;
+       case PROP_FLIP:
+               g_value_set_enum(value, evaspixmapsink->flip);
+               break;
+       case PROP_ROTATE_ANGLE:
+               g_value_set_enum (value, evaspixmapsink->rotate_angle);
+               break;
+       case PROP_VISIBLE:
+               g_value_set_boolean (value, evaspixmapsink->visible);
+               break;
+       case PROP_ORIGIN_SIZE:
+               g_value_set_boolean (value, evaspixmapsink->use_origin_size);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+  }
+}
+
+static void
+gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink)
+{
+       GST_WARNING_OBJECT (evaspixmapsink,"[START]");
+
+       GThread *thread;
+       GST_OBJECT_LOCK (evaspixmapsink);
+       evaspixmapsink->running = FALSE;
+       int i = 0;
+
+       /* grab thread and mark it as NULL */
+       thread = evaspixmapsink->event_thread;
+       evaspixmapsink->event_thread = NULL;
+       GST_OBJECT_UNLOCK (evaspixmapsink);
+
+       /* Wait for our event thread to finish before we clean up our stuff. */
+       if (thread) {
+               g_thread_join (thread);
+       }
+
+       for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+               if(evaspixmapsink->damage[i]) {
+                       g_mutex_lock (evaspixmapsink->x_lock);
+                       XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i]);
+                       g_mutex_unlock (evaspixmapsink->x_lock);
+                       evaspixmapsink->damage[i] = NULL;
+               }
+       }
+       EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( evaspixmapsink->eo );
+
+       if (evaspixmapsink->evas_pixmap_buf) {
+               gst_buffer_unref (GST_BUFFER_CAST (evaspixmapsink->evas_pixmap_buf));
+               evaspixmapsink->evas_pixmap_buf = NULL;
+       }
+
+       for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
+#ifdef DUMP_IMG
+               if (g_bufinfo[i]) {
+                       gst_evaspixmapsink_free_buffer (i);
+                       g_bufinfo[i] = NULL;
+               }
+               evaspixmapsink->pixmap_addr[i] = NULL;
+#endif
+               gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
+               gst_evaspixmapsink_xpixmap_destroy (evaspixmapsink, evaspixmapsink->xpixmap[i]);
+               evaspixmapsink->xpixmap[i] = NULL;
+       }
+       if (evaspixmapsink->eo) {
+               evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
+               evas_object_image_data_set(evaspixmapsink->eo, NULL);
+               evaspixmapsink->eo = NULL;
+       }
+
+       if (evaspixmapsink->epipe) {
+               ecore_pipe_del (evaspixmapsink->epipe);
+               evaspixmapsink->epipe = NULL;
+       }
+
+       evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y =
+       evaspixmapsink->render_rect.w = evaspixmapsink->render_rect.h = 0;
+       evaspixmapsink->have_render_rect = FALSE;
+
+       evaspixmapsink->epipe_request_count = 0;
+
+       gst_evaspixmapsink_xcontext_clear (evaspixmapsink);
+
+       GST_WARNING_OBJECT (evaspixmapsink,"[END]");
+}
+
+/* Finalize is called only once, dispose can be called multiple times.
+ * We use mutexes and don't reset stuff to NULL here so let's register
+ * as a finalize. */
+static void
+gst_evaspixmapsink_finalize (GObject *object)
+{
+       GstEvasPixmapSink *evaspixmapsink;
+       evaspixmapsink = GST_EVASPIXMAPSINK (object);
+       GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
+
+       if (evaspixmapsink->display_name) {
+               g_free (evaspixmapsink->display_name);
+               evaspixmapsink->display_name = NULL;
+       }
+       if (evaspixmapsink->par) {
+               g_free (evaspixmapsink->par);
+               evaspixmapsink->par = NULL;
+       }
+       if (evaspixmapsink->x_lock) {
+               g_mutex_free (evaspixmapsink->x_lock);
+               evaspixmapsink->x_lock = NULL;
+       }
+       if (evaspixmapsink->flow_lock) {
+               g_mutex_free (evaspixmapsink->flow_lock);
+               evaspixmapsink->flow_lock = NULL;
+       }
+       if (evaspixmapsink->pixmap_ref_lock) {
+               g_mutex_free (evaspixmapsink->pixmap_ref_lock);
+               evaspixmapsink->pixmap_ref_lock = NULL;
+       }
+
+       GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
+
+       G_OBJECT_CLASS (parent_class)->finalize (object);
+
+}
+
+static void
+gst_evaspixmapsink_init (GstEvasPixmapSink *evaspixmapsink)
+{
+       int i = 0;
+
+       GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
+
+       evaspixmapsink->display_name = NULL;
+       evaspixmapsink->adaptor_no = 0;
+       evaspixmapsink->xcontext = NULL;
+
+       for (i = 0; i < NUM_OF_PIXMAP; i++) {
+               evaspixmapsink->xpixmap[i] = NULL;
+               evaspixmapsink->damage[i] = 0;
+#ifdef DUMP_IMG
+               g_bufinfo[i] = NULL;
+               evaspixmapsink->pixmap_addr[i] = NULL;
+#endif
+       }
+
+       evaspixmapsink->evas_pixmap_buf = NULL;
+
+       evaspixmapsink->hue = evaspixmapsink->saturation = 0;
+       evaspixmapsink->contrast = evaspixmapsink->brightness = 0;
+       evaspixmapsink->cb_changed = FALSE;
+
+       evaspixmapsink->fps_n = 0;
+       evaspixmapsink->fps_d = 0;
+       evaspixmapsink->video_width = 0;
+       evaspixmapsink->video_height = 0;
+       evaspixmapsink->need_to_fill_black = FALSE;
+
+       evaspixmapsink->x_lock = g_mutex_new ();
+       evaspixmapsink->flow_lock = g_mutex_new ();
+       evaspixmapsink->pixmap_ref_lock = g_mutex_new();
+
+       evaspixmapsink->synchronous = FALSE;
+       evaspixmapsink->double_buffer = TRUE;
+       evaspixmapsink->par = NULL;
+       evaspixmapsink->autopaint_colorkey = TRUE;
+       evaspixmapsink->running = FALSE;
+
+       /* on 16bit displays this becomes r,g,b = 1,2,3
+       * on 24bit displays this becomes r,g,b = 8,8,16
+       * as a port atom value
+       */
+       evaspixmapsink->colorkey = (8 << 16) | (8 << 8) | 16;
+
+       evaspixmapsink->display_geometry_method = DEF_DISPLAY_GEOMETRY_METHOD;
+       evaspixmapsink->dst_roi.x = 0;
+       evaspixmapsink->dst_roi.y = 0;
+       evaspixmapsink->dst_roi.w = 0;
+       evaspixmapsink->dst_roi.h = 0;
+       evaspixmapsink->scr_w = 0;
+       evaspixmapsink->scr_h = 0;
+       evaspixmapsink->aligned_width = 0;
+       evaspixmapsink->aligned_height = 0;
+       evaspixmapsink->stop_video = FALSE;
+       evaspixmapsink->eo = NULL;
+       evaspixmapsink->epipe = NULL;
+       evaspixmapsink->epipe_request_count = 0;
+       evaspixmapsink->do_link = FALSE;
+       evaspixmapsink->flip = DEF_DISPLAY_FLIP;
+       evaspixmapsink->rotate_angle = DEGREE_0;
+       evaspixmapsink->visible = TRUE;
+       evaspixmapsink->update_visibility = UPDATE_FALSE;
+       evaspixmapsink->use_origin_size = FALSE;
+       evaspixmapsink->previous_origin_size = FALSE;
+
+       evaspixmapsink->num_of_pixmaps = NUM_OF_PIXMAP;
+
+       evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_NONE;
+
+       memset(&evaspixmapsink->src_prev, 0, sizeof (GstVideoRectangle));
+       memset(&evaspixmapsink->result_prev, 0, sizeof (GstVideoRectangle));
+
+#ifdef DUMP_IMG
+       g_cnt = 0;
+#endif
+
+       GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
+ }
+
+static void
+gst_evaspixmapsink_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details_simple (element_class,
+      "EvasPixmapSink", "Sink/Video",
+      "evas image object videosink based on Xv extension", "Sangchul Lee <sc11.lee@samsung.com>");
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_evaspixmapsink_sink_template_factory));
+}
+
+static void
+gst_evaspixmapsink_class_init (GstEvasPixmapSinkClass *klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+  GstBaseSinkClass *gstbasesink_class;
+  GstVideoSinkClass *videosink_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+  gstbasesink_class = (GstBaseSinkClass *) klass;
+  videosink_class = (GstVideoSinkClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->set_property = gst_evaspixmapsink_set_property;
+  gobject_class->get_property = gst_evaspixmapsink_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_CONTRAST,
+      g_param_spec_int ("contrast", "Contrast", "The contrast of the video",
+          -1000, 1000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
+      g_param_spec_int ("brightness", "Brightness",
+          "The brightness of the video", -1000, 1000, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_HUE,
+      g_param_spec_int ("hue", "Hue", "The hue of the video", -1000, 1000, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_SATURATION,
+      g_param_spec_int ("saturation", "Saturation",
+          "The saturation of the video", -1000, 1000, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_DISPLAY,
+      g_param_spec_string ("display", "Display", "X Display name", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
+      g_param_spec_boolean ("synchronous", "Synchronous",
+          "When enabled, runs "
+          "the X display in synchronous mode. (used only for debugging)", FALSE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
+      g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
+          "The pixel aspect ratio of the device", "1/1",
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_DEVICE,
+      g_param_spec_string ("device", "Adaptor number",
+          "The number of the video adaptor", "0",
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
+      g_param_spec_string ("device-name", "Adaptor name",
+          "The name of the video adaptor", NULL,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:double-buffer
+   *
+   * Whether to double-buffer the output.
+   *
+   * Since: 0.10.14
+   */
+  g_object_class_install_property (gobject_class, PROP_DOUBLE_BUFFER,
+      g_param_spec_boolean ("double-buffer", "Double-buffer",
+          "Whether to double-buffer the output", TRUE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  /**
+   * GstEvasPixmapSink:autopaint-colorkey
+   *
+   * Whether to autofill overlay with colorkey
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (gobject_class, PROP_AUTOPAINT_COLORKEY,
+      g_param_spec_boolean ("autopaint-colorkey", "Autofill with colorkey",
+          "Whether to autofill overlay with colorkey", TRUE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  /**
+   * GstEvasPixmapSink:colorkey
+   *
+   * Color to use for the overlay mask.
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (gobject_class, PROP_COLORKEY,
+      g_param_spec_int ("colorkey", "Colorkey",
+          "Color to use for the overlay mask", G_MININT, G_MAXINT, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:pixmap-width
+   *
+   * Actual width of the pixmap.
+   */
+  g_object_class_install_property (gobject_class, PROP_PIXMAP_WIDTH,
+      g_param_spec_uint64 ("pixmap-width", "pixmap-width", "Width of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:pixmap-height
+   *
+   * Actual height of the pixmap.
+   */
+  g_object_class_install_property (gobject_class, PROP_PIXMAP_HEIGHT,
+      g_param_spec_uint64 ("pixmap-height", "pixmap-height", "Height of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:display-geometry-method
+   *
+   * Display geometrical method setting
+   */
+  g_object_class_install_property(gobject_class, PROP_DISPLAY_GEOMETRY_METHOD,
+    g_param_spec_enum("display-geometry-method", "Display geometry method",
+      "Geometrical method for display",
+      GST_TYPE_EVASPIXMAPSINK_DISPLAY_GEOMETRY_METHOD, DEF_DISPLAY_GEOMETRY_METHOD,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:dst-roi-x
+   *
+   * X value of Destination ROI
+   */
+  g_object_class_install_property (gobject_class, PROP_DST_ROI_X,
+      g_param_spec_int ("dst-roi-x", "Dst-ROI-X",
+          "X value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:dst-roi-y
+   *
+   * Y value of Destination ROI
+   */
+  g_object_class_install_property (gobject_class, PROP_DST_ROI_Y,
+      g_param_spec_int ("dst-roi-y", "Dst-ROI-Y",
+          "Y value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:dst-roi-w
+   *
+   * W value of Destination ROI
+   */
+  g_object_class_install_property (gobject_class, PROP_DST_ROI_W,
+      g_param_spec_int ("dst-roi-w", "Dst-ROI-W",
+          "W value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:dst-roi-h
+   *
+   * H value of Destination ROI
+   */
+  g_object_class_install_property (gobject_class, PROP_DST_ROI_H,
+      g_param_spec_int ("dst-roi-h", "Dst-ROI-H",
+          "H value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:stop-video
+   *
+   * Stop video for releasing video source buffer
+   */
+  g_object_class_install_property (gobject_class, PROP_STOP_VIDEO,
+      g_param_spec_int ("stop-video", "Stop-Video", "Stop video for releasing video source buffer", 0, 1, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:evas-object
+   *
+   * Evas image object for rendering
+   */
+  g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT,
+    g_param_spec_pointer ("evas-object", "Destination Evas Object",    "Destination evas image object", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:display-flip
+   *
+   * Display flip setting
+   */
+  g_object_class_install_property(gobject_class, PROP_FLIP,
+    g_param_spec_enum("flip", "Display flip",
+      "Flip for display",
+      GST_TYPE_EVASPIXMAPSINK_FLIP, DEF_DISPLAY_FLIP,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:rotate
+   *
+   * draw rotation angle setting
+   */
+  g_object_class_install_property(gobject_class, PROP_ROTATE_ANGLE,
+    g_param_spec_enum("rotate", "Rotate angle", "Rotate angle of display output",GST_TYPE_EVASPIXMAPSINK_ROTATE_ANGLE, DEGREE_0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstEvasPixmapSink:visible
+   *
+   * visible setting for a evas image object
+   */
+  g_object_class_install_property (gobject_class, PROP_VISIBLE,
+       g_param_spec_boolean ("visible", "Visible", "When setting it false, evas image object does not show", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+   /**
+   * GstEvasPixmapSink:origin-size
+   *
+   * Set pixmap size with media source's width and height
+   */
+  g_object_class_install_property (gobject_class, PROP_ORIGIN_SIZE,
+       g_param_spec_boolean ("origin-size", "Origin-Size", "When setting it true, pixmap will be created with media source's width and height", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gobject_class->finalize = gst_evaspixmapsink_finalize;
+
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_change_state);
+  gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_getcaps);
+  gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_setcaps);
+  gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_get_times);
+  gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_event);
+  videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_show_frame);
+}
+
+/* Object typing & Creation */
+GType
+gst_evaspixmapsink_get_type (void)
+{
+  static GType evaspixmapsink_type = 0;
+
+  if (!evaspixmapsink_type) {
+    static const GTypeInfo evaspixmapsink_info = {
+      sizeof (GstEvasPixmapSinkClass),
+      gst_evaspixmapsink_base_init,
+      NULL,
+      (GClassInitFunc) gst_evaspixmapsink_class_init,
+      NULL,
+      NULL,
+      sizeof (GstEvasPixmapSink),
+      0,
+      (GInstanceInitFunc) gst_evaspixmapsink_init,
+    };
+    static const GInterfaceInfo iface_info = {
+      (GInterfaceInitFunc) gst_evaspixmapsink_interface_init,
+      NULL,
+      NULL,
+    };
+    static const GInterfaceInfo navigation_info = {
+      (GInterfaceInitFunc) gst_evaspixmapsink_navigation_init,
+      NULL,
+      NULL,
+    };
+    static const GInterfaceInfo colorbalance_info = {
+      (GInterfaceInitFunc) gst_evaspixmapsink_colorbalance_init,
+      NULL,
+      NULL,
+    };
+    static const GInterfaceInfo propertyprobe_info = {
+      (GInterfaceInitFunc) gst_evaspixmapsink_property_probe_interface_init,
+      NULL,
+      NULL,
+    };
+    evaspixmapsink_type = g_type_register_static (GST_TYPE_VIDEO_SINK, "GstEvasPixmapSink", &evaspixmapsink_info, 0);
+
+    g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
+    g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_NAVIGATION, &navigation_info);
+    g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_COLOR_BALANCE, &colorbalance_info);
+    g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_PROPERTY_PROBE, &propertyprobe_info);
+
+    /* register type and create class in a more safe place instead of at
+     * runtime since the type registration and class creation is not
+     * threadsafe. */
+    g_type_class_ref (gst_evaspixmap_buffer_get_type ());
+  }
+
+  return evaspixmapsink_type;
+}
+
+static gboolean
+plugin_init (GstPlugin *plugin)
+{
+       if (!gst_element_register (plugin, "evaspixmapsink", GST_RANK_NONE, GST_TYPE_EVASPIXMAPSINK)) {
+               return FALSE;
+       }
+       GST_DEBUG_CATEGORY_INIT (gst_debug_evaspixmapsink, "evaspixmapsink", 0, "evaspixmapsink element");
+       GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
+
+       return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
+       "evaspixmapsink","Evas image object render plugin using Xv extension", plugin_init,
+       VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/evaspixmapsink/evaspixmapsink.h b/evaspixmapsink/evaspixmapsink.h
new file mode 100755 (executable)
index 0000000..25d8495
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+ * EvasPixmapSink
+ *
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sangchul Lee <sc11.lee@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_EVASPIXMAPSINK_H__
+#define __GST_EVASPIXMAPSINK_H__
+
+#include <gst/video/gstvideosink.h>
+
+#ifdef HAVE_XSHM
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* HAVE_XSHM */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef HAVE_XSHM
+#include <X11/extensions/XShm.h>
+#endif /* HAVE_XSHM */
+
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/Xdamage.h>
+#include <X11/extensions/damagewire.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+
+#include <Evas.h>
+#include <Ecore.h>
+#include <Ecore_X.h>
+
+#include <tbm_bufmgr.h>
+
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+//#define DUMP_IMG
+
+#define MAX_PLANE_NUM          3
+#define MAX_BUFFER_NUM         20
+#define MAX_GEM_BUFFER_NUM     (MAX_PLANE_NUM * MAX_BUFFER_NUM)
+typedef struct _gem_info_t {
+       int dmabuf_fd;
+       unsigned int gem_handle;
+       unsigned int gem_name;
+       tbm_bo bo;
+       Pixmap ref_pixmap;
+} gem_info_t;
+
+typedef enum {
+       BUF_SHARE_METHOD_NONE = -1,
+       BUF_SHARE_METHOD_PADDR = 0,
+       BUF_SHARE_METHOD_FD,
+       BUF_SHARE_METHOD_TIZEN_BUFFER
+} buf_share_method_t;
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_EVASPIXMAPSINK \
+  (gst_evaspixmapsink_get_type())
+#define GST_EVASPIXMAPSINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_EVASPIXMAPSINK, GstEvasPixmapSink))
+#define GST_EVASPIXMAPSINK_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_EVASPIXMAPSINK, GstEvasPixmapSinkClass))
+#define GST_IS_EVASPIXMAPSINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_EVASPIXMAPSINK))
+#define GST_IS_EVASPIXMAPSINK_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_EVASPIXMAPSINK))
+
+#define XV_SCREEN_SIZE_WIDTH  4096
+#define XV_SCREEN_SIZE_HEIGHT 4096
+
+#define MARGIN_OF_ERROR       0.005
+#define NUM_OF_PIXMAP         3
+
+typedef struct _GstXContext GstXContext;
+typedef struct _GstXPixmap GstXPixmap;
+typedef struct _GstEvasPixmapFormat GstEvasPixmapFormat;
+typedef struct _GstEvasPixmapBuffer GstEvasPixmapBuffer;
+typedef struct _GstEvasPixmapBufferClass GstEvasPixmapBufferClass;
+typedef struct _GstEvasPixmapSink GstEvasPixmapSink;
+typedef struct _GstEvasPixmapSinkClass GstEvasPixmapSinkClass;
+
+/*
+ * GstXContext:
+ * @disp: the X11 Display of this context
+ * @screen: the default Screen of Display @disp
+ * @screen_num: the Screen number of @screen
+ * @visual: the default Visual of Screen @screen
+ * @root: the root Window of Display @disp
+ * @white: the value of a white pixel on Screen @screen
+ * @black: the value of a black pixel on Screen @screen
+ * @depth: the color depth of Display @disp
+ * @bpp: the number of bits per pixel on Display @disp
+ * @endianness: the endianness of image bytes on Display @disp
+ * @width: the width in pixels of Display @disp
+ * @height: the height in pixels of Display @disp
+ * @widthmm: the width in millimeters of Display @disp
+ * @heightmm: the height in millimeters of Display @disp
+ * @par: the pixel aspect ratio calculated from @width, @widthmm and @height,
+ * @heightmm ratio
+ * @use_xshm: used to known wether of not XShm extension is usable or not even
+ * if the Extension is present
+ * @xv_port_id: the XVideo port ID
+ * @im_format: used to store at least a valid format for XShm calls checks
+ * @formats_list: list of supported image formats on @xv_port_id
+ * @channels_list: list of #GstColorBalanceChannels
+ * @caps: the #GstCaps that Display @disp can accept
+ *
+ * Structure used to store various informations collected/calculated for a
+ * Display.
+ */
+struct _GstXContext {
+       Display *disp;
+
+       Screen *screen;
+       gint screen_num;
+
+       Visual *visual;
+
+       Window root;
+
+       gulong white;
+
+       gint depth;
+       gint bpp;
+       gint endianness;
+
+       gint width, height;
+       gint widthmm, heightmm;
+       GValue *par;                  /* calculated pixel aspect ratio */
+
+       gboolean use_xshm;
+
+       XvPortID xv_port_id;
+       guint nb_adaptors;
+       gchar ** adaptors;
+       gint im_format;
+
+       GList *formats_list;
+       GList *channels_list;
+
+       GstCaps *caps;
+};
+
+/*
+ * GstXPixmap:
+ * @pixmap: the pixmap ID of this X11 pixmap
+ * @width: the width in pixels of Pixmap @pixmap
+ * @height: the height in pixels of Pixmap @pixmap
+ * @gc: the Graphical Context of Pixmap @pixmap
+ *
+ * Structure used to store informations about a Pixmap.
+ */
+struct _GstXPixmap {
+       Pixmap pixmap;
+       gint x, y;
+       gint width, height;
+       GC gc;
+       guint ref;
+       gint damaged_time;
+       Pixmap prev_pixmap;
+       GC prev_gc;
+};
+
+/**
+ * GstEvasPixmapFormat:
+ * @format: the image format
+ * @caps: generated #GstCaps for this image format
+ *
+ * Structure storing image format to #GstCaps association.
+ */
+struct _GstEvasPixmapFormat {
+       gint format;
+       GstCaps *caps;
+};
+
+/**
+ * GstEvasPixmapBuffer:
+ * @evaspixmapsink: a reference to our #GstEvasPixmapSink
+ * @xvimage: the XvImage of this buffer
+ * @width: the width in pixels of XvImage @xvimage
+ * @height: the height in pixels of XvImage @xvimage
+ * @im_format: the image format of XvImage @xvimage
+ * @size: the size in bytes of XvImage @xvimage
+ *
+ * Subclass of #GstBuffer containing additional information about an XvImage.
+ */
+struct _GstEvasPixmapBuffer {
+       GstBuffer buffer;
+
+       /* Reference to the evaspixmapsink we belong to */
+       GstEvasPixmapSink *evaspixmapsink;
+       XvImage *xvimage;
+
+#ifdef HAVE_XSHM
+       XShmSegmentInfo SHMInfo;
+#endif /* HAVE_XSHM */
+
+       gint width, height;
+       gint im_format;
+       size_t size;
+};
+
+/**
+ * GstEvasPixmapSink:
+ * @display_name: the name of the Display we want to render to
+ * @xcontext: our instance's #GstXContext
+ * @xpixmap: the #GstXPixmap we are rendering to
+ * @fps_n: the framerate fraction numerator
+ * @fps_d: the framerate fraction denominator
+ * @x_lock: used to protect X calls as we are not using the XLib in threaded
+ * mode
+ * @flow_lock: used to protect data flow routines from external calls such as
+ * methods from the #GstXOverlay interface
+ * @par: used to override calculated pixel aspect ratio from @xcontext
+ * @synchronous: used to store if XSynchronous should be used or not (for
+ * debugging purpose only)
+ * @keep_aspect: used to remember if reverse negotiation scaling should respect
+ * aspect ratio
+ * @brightness: used to store the user settings for color balance brightness
+ * @contrast: used to store the user settings for color balance contrast
+ * @hue: used to store the user settings for color balance hue
+ * @saturation: used to store the user settings for color balance saturation
+ * @cb_changed: used to store if the color balance settings where changed
+ * @video_width: the width of incoming video frames in pixels
+ * @video_height: the height of incoming video frames in pixels
+ *
+ * The #GstEvasPixmapSink data structure.
+ */
+struct _GstEvasPixmapSink {
+       /* Our element stuff */
+       GstVideoSink videosink;
+
+       char *display_name;
+       guint adaptor_no;
+
+       GstXContext *xcontext;
+       GstXPixmap *xpixmap[NUM_OF_PIXMAP];
+       GstEvasPixmapBuffer *evas_pixmap_buf;
+
+       GThread *event_thread;
+       gboolean running;
+
+       gint fps_n;
+       gint fps_d;
+
+       GMutex *x_lock;
+       GMutex *flow_lock;
+       GMutex *pixmap_ref_lock;
+
+       /* object-set pixel aspect ratio */
+       GValue *par;
+
+       gboolean synchronous;
+       gboolean double_buffer;
+
+       gint brightness;
+       gint contrast;
+       gint hue;
+       gint saturation;
+       gboolean cb_changed;
+
+       /* size of incoming video, used as the size for XvImage */
+       guint video_width, video_height;
+       gboolean need_to_fill_black;
+
+       /* display sizes, used for clipping the image */
+       gint disp_x, disp_y;
+       gint disp_width, disp_height;
+
+       /* port attributes */
+       gboolean autopaint_colorkey;
+       gint colorkey;
+
+       /* port features */
+       gboolean have_autopaint_colorkey;
+       gboolean have_colorkey;
+       gboolean have_double_buffer;
+
+       /* target video rectagle */
+       GstVideoRectangle render_rect;
+       gboolean have_render_rect;
+
+       /* display */
+       guint flip;
+       guint rotate_angle;
+       guint display_geometry_method;
+       GstVideoRectangle dst_roi;
+       guint scr_w, scr_h;
+       /* needed if fourcc is one if S series */
+       guint aligned_width;
+       guint aligned_height;
+
+       gboolean stop_video;
+       buf_share_method_t buf_shared_type;
+
+       /* ecore & evas object */
+       Ecore_Pipe *epipe;
+       Evas_Object *eo;
+       Evas_Coord w;
+       Evas_Coord h;
+       gboolean visible;
+       gint last_updated_idx;
+       gchar update_visibility;
+       gint epipe_request_count;
+
+       /* pixmap */
+       gboolean do_link;
+       gboolean use_origin_size;
+       gboolean previous_origin_size;
+       gint sizediff_width;
+       gint sizediff_height;
+       guint num_of_pixmaps;
+
+       /* damage event */
+       Damage damage[NUM_OF_PIXMAP];
+       Damage prev_damage[NUM_OF_PIXMAP];
+       int damage_case;
+
+       gint drm_fd;
+       gem_info_t gem_info[MAX_GEM_BUFFER_NUM];
+
+  /* if needed combine planes data */
+       gint need_combine_data;
+
+       GstVideoRectangle src_prev;
+       GstVideoRectangle result_prev;
+
+#ifdef DUMP_IMG
+       void *pixmap_addr[NUM_OF_PIXMAP];
+#endif
+};
+
+/* max plane count *********************************************************/
+#define MPLANE_IMGB_MAX_COUNT         (4)
+
+/* image buffer definition ***************************************************
+
+    +------------------------------------------+ ---
+    |                                          |  ^
+    |     uaddr[], index[]                     |  |
+    |     +---------------------------+ ---    |  |
+    |     |                           |  ^     |  |
+    |     |<-------- width[] -------->|  |     |  |
+    |     |                           |  |     |  |
+    |     |                           |        |
+    |     |                           |height[]|elevation[]
+    |     |                           |        |
+    |     |                           |  |     |  |
+    |     |                           |  |     |  |
+    |     |                           |  v     |  |
+    |     +---------------------------+ ---    |  |
+    |                                          |  v
+    +------------------------------------------+ ---
+
+    |<----------------- stride[] ------------------>|
+*/
+typedef struct _GstMultiPlaneImageBuffer GstMultiPlaneImageBuffer;
+struct _GstMultiPlaneImageBuffer
+{
+    GstBuffer buffer;
+
+    /* width of each image plane */
+    gint      width[MPLANE_IMGB_MAX_COUNT];
+    /* height of each image plane */
+    gint      height[MPLANE_IMGB_MAX_COUNT];
+    /* stride of each image plane */
+    gint      stride[MPLANE_IMGB_MAX_COUNT];
+    /* elevation of each image plane */
+    gint      elevation[MPLANE_IMGB_MAX_COUNT];
+    /* user space address of each image plane */
+    gpointer uaddr[MPLANE_IMGB_MAX_COUNT];
+    /* Index of real address of each image plane, if needs */
+    gpointer index[MPLANE_IMGB_MAX_COUNT];
+    /* left postion, if needs */
+    gint      x;
+    /* top position, if needs */
+    gint      y;
+    /* to align memory */
+    gint      __dummy2;
+    /* arbitrary data */
+    gint      data[16];
+};
+
+struct _GstEvasPixmapSinkClass {
+  GstVideoSinkClass parent_class;
+};
+
+GType gst_evaspixmapsink_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_EVASPIXMAPSINK_H__ */
diff --git a/evaspixmapsink/xv_types.h b/evaspixmapsink/xv_types.h
new file mode 100644 (file)
index 0000000..8266e34
--- /dev/null
@@ -0,0 +1,101 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*                                                              */
+/* File name : xv_types.h                                       */
+/* Author : Boram Park (boram1288.park@samsung.com)             */
+/* Protocol Version : 1.0.1 (Dec 16th 2009)                       */
+/* This file is for describing Xv APIs' buffer encoding method. */
+/*                                                              */
+
+#ifndef __XV_TYPE_H__
+#define __XV_TYPE_H__
+
+#define XV_DATA_HEADER 0xDEADCD01
+#define XV_DATA_VERSION        0x00010001
+
+/* Return Values */
+#define XV_OK 0
+#define XV_HEADER_ERROR -1
+#define XV_VERSION_MISMATCH -2
+
+/* Video Mode */
+#define DISPLAY_MODE_DEFAULT                                      0
+#define DISPLAY_MODE_PRI_VIDEO_ON_AND_SEC_VIDEO_FULL_SCREEN       1
+#define DISPLAY_MODE_PRI_VIDEO_OFF_AND_SEC_VIDEO_FULL_SCREEN      2
+
+/* Color space range */
+#define CSC_RANGE_NARROW        0
+#define CSC_RANGE_WIDE          1
+
+/* Buffer Type */
+#define XV_BUF_TYPE_DMABUF  0
+#define XV_BUF_TYPE_LEGACY  1
+#define XV_BUF_PLANE_NUM    3
+
+/* Data structure for XvPutImage / XvShmPutImage */
+typedef struct
+{
+    unsigned int _header; /* for internal use only */
+    unsigned int _version; /* for internal use only */
+
+    unsigned int YBuf;
+    unsigned int CbBuf;
+    unsigned int CrBuf;
+    unsigned int BufType;
+    unsigned int dmabuf_fd[XV_BUF_PLANE_NUM];
+    unsigned int gem_handle[XV_BUF_PLANE_NUM];
+    void *bo[XV_BUF_PLANE_NUM];
+} XV_DATA, * XV_DATA_PTR;
+
+static void
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+XV_INIT_DATA (XV_DATA_PTR data)
+{
+    data->_header = XV_DATA_HEADER;
+    data->_version = XV_DATA_VERSION;
+}
+
+static int
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+XV_VALIDATE_DATA (XV_DATA_PTR data)
+{
+    if (data->_header != XV_DATA_HEADER)
+        return XV_HEADER_ERROR;
+    if (data->_version != XV_DATA_VERSION)
+        return XV_VERSION_MISMATCH;
+    return XV_OK;
+}
+
+#endif
diff --git a/gst-plugins-ext0.10.manifest b/gst-plugins-ext0.10.manifest
new file mode 100755 (executable)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
diff --git a/hlsdemux2/Makefile.am b/hlsdemux2/Makefile.am
new file mode 100755 (executable)
index 0000000..308a09c
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = src\r
diff --git a/hlsdemux2/predefined_frame/blackframe_QVGA.264 b/hlsdemux2/predefined_frame/blackframe_QVGA.264
new file mode 100755 (executable)
index 0000000..03e3d8a
Binary files /dev/null and b/hlsdemux2/predefined_frame/blackframe_QVGA.264 differ
diff --git a/hlsdemux2/predefined_frame/sec_audio_fixed_qvga.264 b/hlsdemux2/predefined_frame/sec_audio_fixed_qvga.264
new file mode 100755 (executable)
index 0000000..068599c
Binary files /dev/null and b/hlsdemux2/predefined_frame/sec_audio_fixed_qvga.264 differ
diff --git a/hlsdemux2/predefined_frame/sec_audio_fixed_qvga.jpg b/hlsdemux2/predefined_frame/sec_audio_fixed_qvga.jpg
new file mode 100755 (executable)
index 0000000..55d43b4
Binary files /dev/null and b/hlsdemux2/predefined_frame/sec_audio_fixed_qvga.jpg differ
diff --git a/hlsdemux2/src/Makefile.am b/hlsdemux2/src/Makefile.am
new file mode 100755 (executable)
index 0000000..88525c3
--- /dev/null
@@ -0,0 +1,31 @@
+
+plugin_LTLIBRARIES = libgsthlsdemux2.la
+
+libgsthlsdemux2_la_SOURCES =                   \
+       m3u8.c                                  \
+       gsthlsdemux2.c
+
+libgsthlsdemux2_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(SOUP_CFLAGS) $(GST_APP_CFLAGS) $(CRYPTO_CFLAGS)
+libgsthlsdemux2_la_LIBADD = -lgsttag-@GST_MAJORMINOR@ \
+                $(GST_LIBS) $(GST_BASE_LIBS) $(SOUP_LIBS) $(GST_APP_LIBS) -lgstapp-0.10 $(CRYPTO_LIBS)
+libgsthlsdemux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -no-undefined
+libgsthlsdemux2_la_LIBTOOLFLAGS = --tag=disable-static
+
+# headers we need but don't want installed
+noinst_HEADERS =                       \
+       gsthlsdemux2.h          \
+       m3u8.h
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+       androgenizer \
+       -:PROJECT libgsthls -:SHARED libgsthls \
+        -:TAGS eng debug \
+         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+        -:SOURCES $(libgsthls_la_SOURCES) \
+        -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgsthls_la_CFLAGS) \
+        -:LDFLAGS $(libgsthls_la_LDFLAGS) \
+                  $(libgsthls_la_LIBADD) \
+                  -ldl \
+        -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+                      LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+       > $@
diff --git a/hlsdemux2/src/gsthlsdemux2.c b/hlsdemux2/src/gsthlsdemux2.c
new file mode 100755 (executable)
index 0000000..4f378d2
--- /dev/null
@@ -0,0 +1,5443 @@
+/*
+ * hlsdemux2
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, Naveen Cherukuri <naveen.ch@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * 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.
+ */
+
+#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 <sys/types.h>
+#include <sys/stat.h>
+#include <gst/tag/tag.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <gst/gst.h>
+
+#include "gsthlsdemux2.h"
+
+enum
+{
+  PROP_0,
+  PROP_BITRATE_SWITCH_TOLERANCE,
+  PROP_FORCE_LOWER_BITRATE,
+  PROP_BLOCKSIZE,
+  PROP_LAST
+};
+
+#define HLS_VIDEO_CAPS \
+  GST_STATIC_CAPS (\
+    "video/mpeg, " \
+      "mpegversion = (int) { 1, 2, 4 }, " \
+      "systemstream = (boolean) FALSE; " \
+    "video/x-h264,stream-format=(string)byte-stream," \
+      "alignment=(string)nal;" \
+    "video/x-dirac;" \
+    "video/x-wmv," \
+      "wmvversion = (int) 3, " \
+      "format = (fourcc) WVC1" \
+  )
+
+#define HLS_AUDIO_CAPS \
+  GST_STATIC_CAPS ( \
+    "audio/mpeg, " \
+      "mpegversion = (int) { 1, 4 };" \
+    "audio/x-lpcm, " \
+      "width = (int) { 16, 20, 24 }, " \
+      "rate = (int) { 48000, 96000 }, " \
+      "channels = (int) [ 1, 8 ], " \
+      "dynamic_range = (int) [ 0, 255 ], " \
+      "emphasis = (boolean) { FALSE, TRUE }, " \
+      "mute = (boolean) { FALSE, TRUE }; " \
+    "audio/x-ac3; audio/x-eac3;" \
+    "audio/x-dts;" \
+    "audio/x-private-ts-lpcm;" \
+    "application/x-id3" \
+  )
+
+/* Can also use the subpicture pads for text subtitles? */
+#define HLS_SUBPICTURE_CAPS \
+    GST_STATIC_CAPS ("subpicture/x-pgs; video/x-dvd-subpicture")
+
+static GstStaticPadTemplate hlsdemux2_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("application/x-hls"));
+
+static GstStaticPadTemplate hlsdemux2_videosrc_template =
+GST_STATIC_PAD_TEMPLATE ("video",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    HLS_VIDEO_CAPS);
+
+static GstStaticPadTemplate hlsdemux2_audiosrc_template =
+GST_STATIC_PAD_TEMPLATE ("audio",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    HLS_AUDIO_CAPS);
+
+static GstStaticPadTemplate hlsdemux2_subpicture_template =
+GST_STATIC_PAD_TEMPLATE ("subpicture",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    HLS_SUBPICTURE_CAPS);
+
+static GstStaticPadTemplate hlsdemux2_private_template =
+GST_STATIC_PAD_TEMPLATE ("private",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    GST_STATIC_CAPS_ANY);
+
+GST_DEBUG_CATEGORY_STATIC (gst_hlsdemux2_debug);
+#define GST_CAT_DEFAULT gst_hlsdemux2_debug
+
+GST_DEBUG_CATEGORY (hlsdemux2_m3u8_debug);
+
+static const float update_interval_factor[] = { 1, 0.5, 1.5, 3 };
+
+#define HLS_DEFAULT_FRAME_DURATION (0.04 * GST_SECOND) // 40ms
+#define DEFAULT_BLOCKSIZE (8 * 1024) // 8 kbytes
+#define DEFAULT_FAST_SWITCH_BUFFER_SIZE 0.7 // factor
+static void _do_init (GType type)
+{
+  GST_DEBUG_CATEGORY_INIT (gst_hlsdemux2_debug, "hlsdemux2", 0, "hlsdemux2 element");
+  GST_DEBUG_CATEGORY_INIT (hlsdemux2_m3u8_debug, "hlsdemux2m3u8", 0, "m3u8 parser");
+}
+
+GST_BOILERPLATE_FULL (GstHLSDemux2, gst_hlsdemux2, GstElement, GST_TYPE_ELEMENT, _do_init);
+
+#define DEFAULT_BITRATE_SWITCH_TOLERANCE 0.4
+#define DEFAULT_FAILED_COUNT 3
+#define DEFAULT_TARGET_DURATION 10
+#define DEFAULT_NUM_FRAGMENTS_CACHE 3
+#define DEFAULT_TOTAL_CACHE_DURATION (DEFAULT_NUM_FRAGMENTS_CACHE * DEFAULT_TARGET_DURATION * GST_SECOND)
+
+#define PREDEFINED_VIDEO_FRAME_LOCATION "/usr/etc/sec_audio_fixed_qvga.264"
+//#define PREDEFINED_VIDEO_FRAME_LOCATION "/usr/etc/blackframe_QVGA.264"
+#define PREDEFINED_IMAGE_FRAME_LOCATION "/usr/etc/sec_audio_fixed_qvga.jpg"
+
+#define HLSDEMUX2_SOUP_FAILED_CNT 10
+#define DEFAULT_FORCE_LOWER_BITRATE FALSE
+#define FORCE_LOW_BITRATE_AFTER_CNT 4
+#define HLSDEMUX2_HTTP_TIMEOUT 30 //30sec
+
+enum {
+  HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE = 0,
+  HLSDEMUX2_HTTP_ERROR_RECOVERABLE = 1,
+};
+
+typedef struct _HLSDemux2_HTTP_error HLSDemux2_HTTP_error;
+
+typedef gboolean (*HLS_HTTP_error_handle_function) (GstHLSDemux2 *demux, gchar *element_name);
+
+struct _HLSDemux2_HTTP_error {
+  guint HTTP_error_code;
+  const gchar *error_phrase;
+  guint error_type;
+  HLS_HTTP_error_handle_function handle_error;
+};
+
+struct _GstHLSDemux2PvtStream
+{
+  void *parent;
+  GstPad *sinkpad;
+  GstElement *sink;
+  gulong sink_eprobe;
+  gulong sink_bprobe;
+  HLSDEMUX2_STREAM_TYPE type;
+  GValue      codec_type;
+  GstBuffer  *id3_buffer;
+  GstBuffer  *image_buffer;
+  GstBuffer  *video_buffer;
+  gboolean    got_img_buffer;
+  GstElement *convert_pipe;
+  GCond      *img_load_cond;
+  GMutex     *img_load_lock;
+  GCond      *convert_cond;
+  GMutex     *convert_lock;
+};
+
+struct _GstHLSDemux2Stream
+{
+  void *parent;
+  GstPad *pad;
+  GQueue *queue;
+  GMutex *queue_lock;
+  GCond *queue_full;
+  GCond *queue_empty;
+  gint64 percent;
+  HLSDEMUX2_STREAM_TYPE type;
+  gboolean is_linked;
+  gboolean eos;
+  gboolean apply_disc;
+  gint64 cached_duration;
+  GThread *dummy_data_thread; /* for pushing dummy video data */
+  GstClockTime base_ts; /* base ts start */
+  GstClockTime fts; /* first valid timestamp in a fragment */
+  GstClockTime lts; /* last valid timestamp in a fragment */
+  /* expected first timestamp in next fragment : usefule for handling fragments discontinuities*/
+  GstClockTime nts;
+  GstClockTime prev_nts; /* stores last nts for handling .aac files */
+  gboolean valid_fts_rcvd;
+  GstClockTime cdisc; /* current disc time */
+  GstClockTime frame_duration;
+  guint64 total_stream_time;
+  GstClockTime total_disc;
+  GQueue *downloader_queue;
+  gboolean need_newsegment;
+  GstEvent *newsegment;
+};
+
+/* GStreamer virtual functions */
+static void gst_hlsdemux2_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_hlsdemux2_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static gboolean gst_hlsdemux2_sink_event (GstPad * pad, GstEvent * event);
+static GstStateChangeReturn gst_hlsdemux2_change_state (GstElement * element, GstStateChange transition);
+static void gst_hlsdemux2_dispose (GObject * obj);
+static GstFlowReturn gst_hlsdemux2_chain (GstPad * pad, GstBuffer * buf);
+static gboolean gst_hlsdemux2_handle_src_event (GstPad * pad, GstEvent * event);
+
+/* init & de-init functions */
+static void gst_hlsdemux2_private_init (GstHLSDemux2 *demux);
+static void gst_hlsdemux2_private_deinit (GstHLSDemux2 *demux);
+static void gst_hlsdemux2_playlist_downloader_init (GstHLSDemux2 *demux);
+static void gst_hlsdemux2_playlist_downloader_deinit (GstHLSDemux2 *demux);
+static void gst_hlsdemux2_key_downloader_init (GstHLSDemux2 *demux);
+static void gst_hlsdemux2_key_downloader_deinit (GstHLSDemux2 *demux);
+static void gst_hlsdemux2_fragment_downloader_init (GstHLSDemux2 *demux);
+static void gst_hlsdemux2_fragment_downloader_deinit (GstHLSDemux2 *demux);
+
+/* helper functions */
+static void gst_hlsdemux2_stop (GstHLSDemux2 * demux);
+static gboolean gst_hlsdemux2_set_location (GstHLSDemux2 * demux, const gchar * uri);
+static gchar *gst_hlsdemux2_src_buf_to_utf8_playlist (GstBuffer * buf);
+static void gst_hlsdemux2_new_pad_added (GstElement *element, GstPad *pad, gpointer data);
+static void gst_hlsdemux2_get_cookies(GstHLSDemux2 *demux);
+static void gst_hlsdemux2_get_user_agent(GstHLSDemux2 *demux);
+static gboolean gst_hlsdemux2_update_playlist (GstHLSDemux2 * demux, gboolean update, gboolean *is_error);
+static gboolean gst_hlsdemux2_schedule (GstHLSDemux2 * demux);
+static void gst_hlsdemux2_calculate_pushed_duration (GstHLSDemux2 *demux, GstHLSDemux2Stream *stream,
+    GstBuffer *inbuf);
+
+/* stream specific functions */
+static void gst_hlsdemux2_stream_init (GstHLSDemux2 *demux, GstHLSDemux2Stream *stream,
+    HLSDEMUX2_STREAM_TYPE stream_type, gchar *name, GstCaps *src_caps);
+static void gst_hlsdemux2_stream_deinit (GstHLSDemux2Stream *stream, gpointer data);
+static void gst_hlsdemux2_stop_stream (GstHLSDemux2 *demux);
+static HLSDemux2SinkBin *gst_hlsdemux2_create_stream (GstHLSDemux2 *demux, gchar *name, GstCaps *caps);
+
+/* task functions */
+static void gst_hlsdemux2_push_loop (GstHLSDemux2Stream *stream);
+static void gst_hlsdemux2_fragment_download_loop (GstHLSDemux2 * demux);
+
+/* playlist download related functions */
+static void gst_hlsdemux2_on_playlist_buffer (GstElement * appsink, void* data);
+static GstBusSyncReply gst_hlsdemux2_playlist_download_bus_sync_cb (GstBus * bus, GstMessage *msg, gpointer data);
+
+/* key file download related functions */
+static gboolean gst_hlsdemux2_key_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data);
+static void gst_hlsdemux2_on_key_buffer (GstElement *appsink, void *data);
+
+/* fragment download related functions */
+static gboolean gst_hlsdemux2_fragment_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data);
+static void gst_hlsdemux2_downloader_new_buffer (GstElement *appsink, void *user_data);
+static void gst_hlsdemux2_downloader_eos (GstElement * appsink, void* user_data);
+
+/* probe functions */
+static gboolean gst_hlsdemux2_sink_event_handler (GstPad * pad, GstEvent * event, gpointer data);
+static gboolean gst_hlsdemux2_change_playlist (GstHLSDemux2 * demux, guint max_bitrate, gboolean *is_switched);
+static gboolean gst_hlsdemux2_download_monitor_thread (GstHLSDemux2 *demux);
+static void gst_hlsdemux2_push_eos (GstHLSDemux2 *demux);
+static void gst_hlsdemux2_apply_disc (GstHLSDemux2 * demux);
+static gboolean gst_hlsdemux2_queue_buffer_handler (GstPad * pad, GstBuffer *buffer, gpointer data);
+static gboolean hlsdemux2_HTTP_not_found(GstHLSDemux2 *demux, gchar *element_name);
+static gboolean hlsdemux2_HTTP_time_out (GstHLSDemux2 *demux, gchar *element_name);
+static gboolean hlsdemux2_HTTP_repeat_request (GstHLSDemux2 *demux, gchar *element_name);
+static void gst_hlsdemux2_handle_private_pad (GstHLSDemux2 *demux, GstPad *srcpad);
+static void gst_hlsdemux2_private_sink_on_new_buffer (GstElement *appsink, void *user_data);
+static void gst_hlsdemux2_private_sink_on_eos (GstElement * appsink, void* user_data);
+static gboolean gst_hlsdemux2_imagebuf_pipe_bus_cb (GstBus *bus, GstMessage *msg, gpointer data);
+static gboolean gst_hlsdemux2_set_video_buffer (GstPad * srcpad, GstBuffer * buffer, gpointer user_data);
+static gboolean gst_hlsdemux2_done_video_buffer (GstPad * srcpad, GstEvent * event, gpointer user_data);
+static gboolean gst_hlsdemux2_check_fast_switch (GstHLSDemux2 *demux);
+
+static const HLSDemux2_HTTP_error http_errors[] = {
+
+  /* transport errors by libsoup */
+  { 1, "Cancelled", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 2, "Cannot resolve hostname", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 3, "Cannot resolve proxy hostname", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 4, "Cannot connect to destination", HLSDEMUX2_HTTP_ERROR_RECOVERABLE, hlsdemux2_HTTP_repeat_request },
+  { 5, "Cannot connect to proxy", HLSDEMUX2_HTTP_ERROR_RECOVERABLE, hlsdemux2_HTTP_repeat_request },
+  { 6, "SSL handshake failed", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 7, "Connection terminated unexpectedly", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 8, "Message Corrupt", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 9, "Too many redirects", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+
+  /* Client error */
+  { 400, "Bad Request", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 401, "Unauthorized", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 402, "Payment Required", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 403, "Forbidden", HLSDEMUX2_HTTP_ERROR_RECOVERABLE, hlsdemux2_HTTP_repeat_request }, // TODO: Currently taking it as recoverable for testing
+  { 404, "Not Found", HLSDEMUX2_HTTP_ERROR_RECOVERABLE, hlsdemux2_HTTP_not_found },
+  { 405, "Method Not Allowed", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 406, "Not Acceptable", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 407, "Proxy Authentication Required", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 408, "Request Timeout", HLSDEMUX2_HTTP_ERROR_RECOVERABLE, hlsdemux2_HTTP_time_out },
+  { 409, "Conflict", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 410, "Gone", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 411, "Length Required", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 412, "Precondition Failed", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 413, "Request Entity Too Large", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 414, "Request-URI Too Long", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 415, "Unsupported Media Type", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 416, "Requested Range Not Satisfiable", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 417, "Expectation Failed", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 418, "Unprocessable Entity", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 419, "Locked", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 420, "Failed Dependency", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+
+  /* Server error */
+  { 500, "Internal Server Error", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 501, "Not Implemented", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 502, "Bad Gateway", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 503, "Service Unavailable", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL }, // TODO: need to make as recoverable with timout value
+  { 504, "Gateway Timeout", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 505, "HTTP Version Not Supported", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 506, "Insufficient Storage", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+  { 507, "Not Extended", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
+};
+
+
+static void
+gst_hlsdemux2_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 (&hlsdemux2_videosrc_template));
+  gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&hlsdemux2_audiosrc_template));
+  gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&hlsdemux2_subpicture_template));
+  gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&hlsdemux2_sink_template));
+
+  gst_element_class_set_details_simple (element_class,
+      "HLS Demuxer2",
+      "Demuxer/URIList",
+      "HTTP Live Streaming (HLS) demuxer",
+      "Naveen Cherukuri<naveen.ch@samsung.com>");
+}
+
+static void
+gst_hlsdemux2_class_init (GstHLSDemux2Class * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  gobject_class->set_property = gst_hlsdemux2_set_property;
+  gobject_class->get_property = gst_hlsdemux2_get_property;
+  gobject_class->dispose = gst_hlsdemux2_dispose;
+
+  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));
+
+  g_object_class_install_property (gobject_class, PROP_FORCE_LOWER_BITRATE,
+      g_param_spec_boolean ("force-low-bitrate",
+          "forcing lower variant", "forcing lower variant after every few fragments [for debugging purpose only]",
+          DEFAULT_FORCE_LOWER_BITRATE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,
+      g_param_spec_ulong ("blocksize", "Block size",
+          "Size in bytes to read per buffer (-1 = default)", 0, G_MAXULONG,
+          DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_hlsdemux2_change_state);
+}
+
+static void
+gst_hlsdemux2_init (GstHLSDemux2 * demux, GstHLSDemux2Class * klass)
+{
+  /* sink pad */
+  demux->sinkpad = gst_pad_new_from_static_template (&hlsdemux2_sink_template, "sink");
+  gst_pad_set_chain_function (demux->sinkpad, GST_DEBUG_FUNCPTR (gst_hlsdemux2_chain));
+  gst_pad_set_event_function (demux->sinkpad, GST_DEBUG_FUNCPTR (gst_hlsdemux2_sink_event));
+  gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
+
+  gst_hlsdemux2_private_init (demux);
+
+  /* fragment downloader init */
+  gst_hlsdemux2_fragment_downloader_init (demux);
+
+  /* playlist downloader init */
+  gst_hlsdemux2_playlist_downloader_init (demux);
+
+  /* key downloader init */
+  gst_hlsdemux2_key_downloader_init (demux);
+
+}
+
+static void
+gst_hlsdemux2_dispose (GObject * obj)
+{
+  GstHLSDemux2 *demux = GST_HLSDEMUX2 (obj);
+
+  GST_INFO_OBJECT (demux,"entering");
+
+  gst_hlsdemux2_stop (demux);
+
+  gst_hlsdemux2_private_deinit (demux);
+
+  gst_hlsdemux2_fragment_downloader_deinit (demux);
+
+  gst_hlsdemux2_playlist_downloader_deinit (demux);
+
+  gst_hlsdemux2_key_downloader_deinit (demux);
+
+  GST_INFO_OBJECT (demux,"leaving");
+
+  G_OBJECT_CLASS (parent_class)->dispose (obj);
+}
+
+static void
+gst_hlsdemux2_private_init (GstHLSDemux2 *demux)
+{
+  demux->is_live = TRUE;
+  demux->bitrate_switch_tol = DEFAULT_BITRATE_SWITCH_TOLERANCE;
+  demux->percent = 100;
+  demux->active_stream_cnt = 0;
+  demux->download_task = NULL;
+  demux->pl_update_lock = g_mutex_new ();
+  demux->pl_update_cond = g_cond_new ();
+  demux->cancelled = FALSE;
+  demux->total_cache_duration = DEFAULT_TOTAL_CACHE_DURATION;
+  demux->target_duration = DEFAULT_TARGET_DURATION;
+  demux->keyCookie = NULL;
+  demux->playlistCookie = NULL;
+  demux->fragCookie = NULL;
+  demux->lastCookie = NULL;
+  demux->keyDomain = NULL;
+  demux->playlistDomain = NULL;
+  demux->fragDomain = NULL;
+  demux->lastDomain = NULL;
+  demux->user_agent = NULL;
+  demux->buffering_lock = g_mutex_new ();
+  demux->soup_request_fail_cnt = HLSDEMUX2_SOUP_FAILED_CNT;
+  demux->force_lower_bitrate = DEFAULT_FORCE_LOWER_BITRATE;
+  demux->cfrag_dur = 0;
+  demux->error_posted = FALSE;
+  demux->playlist_uri = NULL;
+  demux->frag_uri = NULL;
+  demux->key_uri = NULL;
+  demux->blocksize = DEFAULT_BLOCKSIZE;
+  demux->flushing = FALSE;
+  demux->ns_start = 0;
+  demux->cur_audio_fts = GST_CLOCK_TIME_NONE;
+  demux->is_buffering = TRUE;
+  demux->buffering_posting_thread = NULL;
+  demux->post_msg_lock = g_mutex_new ();
+  demux->post_msg_start = g_cond_new ();
+  demux->post_msg_exit = g_cond_new ();
+  demux->stream_config = HLSDEMUX2_SINGLE_VARIANT;
+  demux->has_image_buffer = FALSE;
+  demux->prev_image_buffer = NULL;
+  demux->prev_video_buffer = NULL;
+  demux->private_stream = NULL;
+}
+
+static void
+gst_hlsdemux2_private_deinit (GstHLSDemux2 *demux)
+{
+  demux->end_of_playlist = FALSE;
+
+  if (demux->pl_update_lock) {
+    g_mutex_free (demux->pl_update_lock);
+    demux->pl_update_lock = NULL;
+  }
+
+  if (demux->pl_update_cond) {
+    g_cond_free (demux->pl_update_cond);
+    demux->pl_update_cond = NULL;
+  }
+
+  if (demux->buffering_lock) {
+    g_mutex_free (demux->buffering_lock);
+    demux->buffering_lock = NULL;
+  }
+
+  if (demux->user_agent) {
+    g_free (demux->user_agent);
+    demux->user_agent = NULL;
+  }
+
+  if (demux->playlist) {
+    gst_buffer_unref (demux->playlist);
+    demux->playlist = NULL;
+  }
+
+  if (demux->fragCookie) {
+    g_strfreev (demux->fragCookie);
+    demux->fragCookie = NULL;
+  }
+
+  if (demux->keyCookie) {
+    g_strfreev (demux->keyCookie);
+    demux->keyCookie = NULL;
+  }
+
+  if (demux->lastCookie) {
+    g_strfreev (demux->lastCookie);
+    demux->lastCookie = NULL;
+  }
+
+  if (demux->playlistCookie) {
+    g_strfreev (demux->playlistCookie);
+    demux->playlistCookie = NULL;
+  }
+
+  if (demux->fragDomain) {
+    g_free (demux->fragDomain);
+    demux->fragDomain = NULL;
+  }
+
+  if (demux->keyDomain) {
+    g_free (demux->keyDomain);
+    demux->keyDomain = NULL;
+  }
+
+  if (demux->lastDomain) {
+    g_free (demux->lastDomain);
+    demux->lastDomain = NULL;
+  }
+
+  if (demux->playlistDomain) {
+    g_free (demux->playlistDomain);
+    demux->playlistDomain = NULL;
+  }
+
+  if (demux->playlist_uri) {
+    g_free (demux->playlist_uri);
+    demux->playlist_uri = NULL;
+  }
+
+  if (demux->key_uri) {
+    g_free (demux->key_uri);
+    demux->key_uri = NULL;
+  }
+
+  if (demux->frag_uri) {
+    g_free (demux->frag_uri);
+    demux->frag_uri = NULL;
+  }
+
+  if (demux->prev_image_buffer) {
+    gst_buffer_unref (demux->prev_image_buffer);
+    demux->prev_image_buffer = NULL;
+  }
+
+  if (demux->prev_video_buffer) {
+    gst_buffer_unref (demux->prev_video_buffer);
+    demux->prev_video_buffer = NULL;
+  }
+
+  if (demux->private_stream) {
+    g_free (demux->private_stream);
+    demux->private_stream = NULL;
+  }
+
+  if (demux->client) {
+    gst_m3u8_client_free (demux->client);
+    demux->client = NULL;
+  }
+}
+
+static void
+gst_hlsdemux2_fragment_downloader_init (GstHLSDemux2 *demux)
+{
+  demux->fdownloader = g_new0 (HLSDemux2FragDownloader, 1);
+  demux->fdownloader->pipe = NULL;
+  demux->fdownloader->urisrc = NULL;
+  demux->fdownloader->queue = NULL;
+  demux->fdownloader->typefind = NULL;
+  demux->fdownloader->demuxer = NULL;
+  demux->fdownloader->sinkbins = NULL;
+  demux->fdownloader->lock = g_mutex_new ();
+  demux->fdownloader->cond = g_cond_new ();
+  demux->fdownloader->is_encrypted = FALSE;
+  demux->fdownloader->content_size = 0;
+  demux->fdownloader->get_next_frag = FALSE;
+  demux->fdownloader->applied_fast_switch = FALSE;
+  demux->fdownloader->remaining_data = NULL;
+  demux->fdownloader->remaining_size = 0;
+  demux->fdownloader->first_buffer = TRUE;
+  demux->fdownloader->cur_stream_cnt = 0;
+  demux->fdownloader->force_timestamps = FALSE;
+  demux->fdownloader->error_rcvd = FALSE;
+  demux->fdownloader->find_mediaseq = FALSE;
+  demux->fdownloader->seeked_pos = 0;
+  demux->fdownloader->cur_running_dur = 0;
+  demux->fdownloader->download_rate = -1;
+  demux->fdownloader->download_start_ts = 0;
+  demux->fdownloader->download_stop_ts = 0;
+  demux->fdownloader->src_downloaded_size = 0;
+  demux->fdownloader->queue_downloaded_size = 0;
+  demux->fdownloader->ndownloaded = 0;
+  demux->fdownloader->chunk_downloaded_size = 0;
+  demux->fdownloader->chunk_start_ts = 0;
+  demux->fdownloader->avg_chunk_drates = g_array_new(FALSE, TRUE, sizeof(guint64));
+  demux->fdownloader->avg_frag_drates = g_array_new(FALSE, TRUE, sizeof(guint64));
+}
+
+static void
+gst_hlsdemux2_fragment_downloader_deinit (GstHLSDemux2 *demux)
+{
+  if (!demux->fdownloader)
+    return;
+
+  /* free fragment downloader structure */
+  if (demux->fdownloader->lock) {
+    g_mutex_free (demux->fdownloader->lock);
+    demux->fdownloader->lock = NULL;
+  }
+
+  if (demux->fdownloader->cond) {
+    g_cond_free (demux->fdownloader->cond);
+    demux->fdownloader->cond = NULL;
+  }
+
+  if (demux->fdownloader->remaining_data) {
+    g_free (demux->fdownloader->remaining_data);
+    demux->fdownloader->remaining_data = NULL;
+  }
+
+  if (demux->fdownloader->avg_chunk_drates) {
+    g_array_free(demux->fdownloader->avg_chunk_drates, TRUE);
+    demux->fdownloader->avg_chunk_drates = NULL;
+  }
+
+  if (demux->fdownloader->avg_frag_drates) {
+    g_array_free(demux->fdownloader->avg_frag_drates, TRUE);
+    demux->fdownloader->avg_frag_drates = NULL;
+  }
+
+  g_free (demux->fdownloader);
+  demux->fdownloader = NULL;
+}
+
+static void
+gst_hlsdemux2_playlist_downloader_init (GstHLSDemux2 *demux)
+{
+  demux->pldownloader = g_new0 (HLSDemux2PLDownloader, 1);
+  demux->pldownloader->pipe = NULL;
+  demux->pldownloader->bus = NULL;
+  demux->pldownloader->urisrc = NULL;
+  demux->pldownloader->sink = NULL;
+  demux->pldownloader->lock = g_mutex_new ();
+  demux->pldownloader->cond = g_cond_new ();
+  demux->pldownloader->playlist = NULL;
+  demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
+}
+
+static void
+gst_hlsdemux2_playlist_downloader_deinit (GstHLSDemux2 *demux)
+{
+  if (!demux->pldownloader)
+    return;
+
+  /* free playlist downloader structure */
+  if (demux->pldownloader->lock) {
+    g_mutex_free (demux->pldownloader->lock);
+    demux->pldownloader->lock = NULL;
+  }
+
+  if (demux->pldownloader->cond) {
+    g_cond_free (demux->pldownloader->cond);
+    demux->pldownloader->cond = NULL;
+  }
+
+  if (demux->pldownloader->playlist){
+    gst_buffer_unref (demux->pldownloader->playlist);
+    demux->pldownloader->playlist = NULL;
+  }
+
+  g_free (demux->pldownloader);
+  demux->pldownloader = NULL;
+}
+
+static void
+gst_hlsdemux2_key_downloader_init (GstHLSDemux2 *demux)
+{
+  demux->kdownloader = g_new0 (HLSDemux2KeyDownloader, 1);
+  demux->kdownloader->pipe = NULL;
+  demux->kdownloader->bus = NULL;
+  demux->kdownloader->urisrc = NULL;
+  demux->kdownloader->sink = NULL;
+  demux->kdownloader->lock = g_mutex_new ();
+  demux->kdownloader->cond = g_cond_new ();
+  demux->kdownloader->key = NULL;
+  demux->kdownloader->prev_key_uri = NULL;
+}
+
+static void
+gst_hlsdemux2_key_downloader_deinit (GstHLSDemux2 *demux)
+{
+  /* free key file downloader structure */
+  if (!demux->kdownloader)
+    return;
+
+  if (demux->kdownloader->lock) {
+    g_mutex_free (demux->kdownloader->lock);
+    demux->kdownloader->lock = NULL;
+  }
+
+  if (demux->kdownloader->cond) {
+    g_cond_free (demux->kdownloader->cond);
+    demux->kdownloader->cond = NULL;
+  }
+
+  if (demux->kdownloader->key){
+    gst_buffer_unref (demux->kdownloader->key);
+    demux->kdownloader->key = NULL;
+  }
+
+  if (demux->kdownloader->prev_key_uri) {
+    g_free (demux->kdownloader->prev_key_uri);
+    demux->kdownloader->prev_key_uri = NULL;
+  }
+
+  g_free (demux->kdownloader);
+  demux->kdownloader = NULL;
+}
+
+static void
+gst_hlsdemux2_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstHLSDemux2 *demux = GST_HLSDEMUX2 (object);
+
+  switch (prop_id) {
+    case PROP_BITRATE_SWITCH_TOLERANCE:
+      demux->bitrate_switch_tol = g_value_get_float (value);
+      break;
+    case PROP_FORCE_LOWER_BITRATE:
+      demux->force_lower_bitrate = g_value_get_boolean (value);
+      break;
+    case PROP_BLOCKSIZE:
+      demux->blocksize = g_value_get_ulong (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_hlsdemux2_get_property (GObject * object, guint prop_id,
+   GValue * value, GParamSpec * pspec)
+{
+  GstHLSDemux2 *demux = GST_HLSDEMUX2 (object);
+
+  switch (prop_id) {
+    case PROP_BITRATE_SWITCH_TOLERANCE:
+      g_value_set_float (value, demux->bitrate_switch_tol);
+      break;
+    case PROP_FORCE_LOWER_BITRATE:
+      g_value_set_boolean (value, demux->force_lower_bitrate);
+      break;
+    case PROP_BLOCKSIZE:
+      g_value_set_ulong (value, demux->blocksize);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+gst_hlsdemux2_sink_event (GstPad * pad, GstEvent * event)
+{
+  GstHLSDemux2 *demux = GST_HLSDEMUX2 (gst_pad_get_parent (pad));
+  GstQuery *query = NULL;
+  gboolean ret = FALSE;
+  gchar *uri = NULL;
+
+  GST_LOG_OBJECT (demux, "Received event '%s' on sink pad...", GST_EVENT_TYPE_NAME (event));
+
+  switch (event->type) {
+    case GST_EVENT_EOS: {
+      gchar *playlist = NULL;
+      GError *err = NULL;
+
+      if (demux->playlist == NULL) {
+        GST_ERROR_OBJECT (demux, "Received EOS without a playlist.");
+        goto error;
+      }
+
+      GST_INFO_OBJECT (demux, "Got EOS on the sink pad: playlist file fetched");
+
+      query = gst_query_new_uri ();
+
+      /* query the location from upstream element for absolute path */
+      ret = gst_pad_peer_query (demux->sinkpad, query);
+      if (ret) {
+        gst_query_parse_uri (query, &uri);
+        gst_hlsdemux2_set_location (demux, uri);
+        g_free (uri);
+      } else {
+        GST_ERROR_OBJECT (demux, "failed to query URI from upstream");
+        goto error;
+      }
+      gst_query_unref (query);
+      query = NULL;
+
+      /* get cookies from upstream httpsrc */
+      gst_hlsdemux2_get_cookies (demux);
+
+      /* get user-agent from upstream httpsrc */
+      gst_hlsdemux2_get_user_agent (demux);
+
+      playlist = gst_hlsdemux2_src_buf_to_utf8_playlist (demux->playlist);
+      demux->playlist = NULL;
+
+      if (playlist == NULL) {
+        GST_ERROR_OBJECT (demux, "Error validating first playlist.");
+        GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid playlist."), (NULL));
+        goto error;
+      }
+
+      if (!gst_m3u8_client_update (demux->client, playlist)) {
+        /* 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_ERROR_OBJECT (demux, "failed to parse playlist...");
+        GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid playlist."), (NULL));
+        goto error;
+      }
+
+      /* Loop to download the fragments & updates playlist */
+      g_static_rec_mutex_init (&demux->download_lock);
+      demux->download_task = gst_task_create ((GstTaskFunction) gst_hlsdemux2_fragment_download_loop, demux);
+      if (NULL == demux->download_task) {
+        GST_ERROR_OBJECT (demux, "failed to create download task...");
+        GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to fragment download task"), (NULL));
+        goto error;
+      }
+      gst_task_set_lock (demux->download_task, &demux->download_lock);
+      gst_task_start (demux->download_task);
+
+      /* create thread to send dummy data */
+      demux->buffering_posting_thread = g_thread_create (
+        (GThreadFunc) gst_hlsdemux2_download_monitor_thread, demux, TRUE, &err);
+
+      /* Swallow EOS, we'll push our own */
+      gst_event_unref (event);
+      gst_object_unref (demux);
+      return TRUE;
+    }
+    case GST_EVENT_NEWSEGMENT:
+      /* Swallow newsegments, we'll push our own */
+      gst_event_unref (event);
+      gst_object_unref (demux);
+      return TRUE;
+    default:
+      gst_object_unref (demux);
+      break;
+  }
+
+  return gst_pad_event_default (pad, event);
+
+error:
+  gst_hlsdemux2_stop (demux);
+  gst_event_unref (event);
+  gst_object_unref (demux);
+
+  if (query)
+    gst_query_unref (query);
+
+  GST_LOG_OBJECT (demux,"Returning from sink event...");
+  return FALSE;
+}
+
+static GstStateChangeReturn
+  gst_hlsdemux2_change_state (GstElement * element, GstStateChange transition)
+  {
+    GstStateChangeReturn ret;
+    GstHLSDemux2 *demux = GST_HLSDEMUX2 (element);
+    gboolean bret = FALSE;
+
+    switch (transition) {
+      case GST_STATE_CHANGE_READY_TO_PAUSED:
+        break;
+      case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+        GST_INFO_OBJECT (demux,"PAUSED->PLAYING");
+        break;
+      case GST_STATE_CHANGE_PAUSED_TO_READY:
+        GST_INFO_OBJECT (demux,"PAUSED->READY before parent");
+        gst_hlsdemux2_stop (demux);
+        break;
+      default:
+        break;
+    }
+
+    ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+    switch (transition) {
+      case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+        GST_INFO_OBJECT (demux,"PLAYING->PAUSED");
+        break;
+      case GST_STATE_CHANGE_PAUSED_TO_READY:
+        GST_INFO_OBJECT (demux,"PAUSED->READY after parent");
+        if (demux->download_task) {
+          bret = gst_task_join (demux->download_task);
+          GST_DEBUG_OBJECT (demux,"Joining download task : %d", bret);
+        }
+        break;
+      case GST_STATE_CHANGE_READY_TO_NULL:
+        GST_INFO_OBJECT (demux,"READY->NULL");
+        break;
+      default:
+        break;
+    }
+    return ret;
+  }
+
+
+
+static GstFlowReturn
+gst_hlsdemux2_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstHLSDemux2 *demux = GST_HLSDEMUX2 (gst_pad_get_parent (pad));
+
+  if (demux->playlist == NULL)
+    demux->playlist = buf;
+  else
+    demux->playlist = gst_buffer_join (demux->playlist, buf);
+  gst_object_unref (demux);
+
+  return GST_FLOW_OK;
+}
+
+static gboolean
+gst_hlsdemux2_handle_src_event (GstPad * pad, GstEvent * event)
+{
+  GstHLSDemux2 *hlsdemux2 = NULL;
+  GstHLSDemux2Stream *stream = NULL;
+
+  stream = (GstHLSDemux2Stream *) (gst_pad_get_element_private (pad));
+  hlsdemux2 = stream->parent;
+
+  switch (event->type) {
+    case GST_EVENT_SEEK: {
+      gdouble rate;
+      GstFormat format;
+      GstSeekFlags flags;
+      GstSeekType start_type, stop_type;
+      gint64 start, stop;
+      gint idx = 0;
+
+      if (gst_m3u8_client_is_live (hlsdemux2->client)) {
+        GST_WARNING_OBJECT (stream->pad, "SEEK is NOT Supported in LIVE");
+        return FALSE;
+      }
+
+      GST_INFO_OBJECT (stream->pad, "received SEEK event..");
+
+      gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
+                &stop_type, &stop);
+
+      if (format != GST_FORMAT_TIME) {
+        GST_WARNING_OBJECT (stream->pad, "received seek with unsupported format");
+        return FALSE;
+      }
+
+      // TODO: Validate requested SEEK time is within the duration or not
+
+      hlsdemux2->end_of_playlist = FALSE; // resent end of playlist
+
+      GST_DEBUG_OBJECT (stream->pad, "SEEK event with rate: %f start: %" GST_TIME_FORMAT
+          " stop: %" GST_TIME_FORMAT, rate, GST_TIME_ARGS (start),
+          GST_TIME_ARGS (stop));
+
+      if (!(flags & GST_SEEK_FLAG_FLUSH)) {
+        GST_WARNING_OBJECT (stream->pad, "non-flush seek is not supported yet");
+        return FALSE;
+      }
+
+      hlsdemux2->flushing = TRUE;
+
+      /* signal queue full condition to come out */
+      for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+        GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
+
+        if (cur_stream) {
+          cur_stream->eos = FALSE; // resent stream EOS
+          if (cur_stream->queue) {
+            GST_INFO_OBJECT (cur_stream->pad, "signalling stream queue");
+            g_cond_signal (cur_stream->queue_full); /* to signal downloader eos blocking */
+            g_cond_signal (cur_stream->queue_empty); /* incase push_loop blocked on condition */
+          }
+        }
+      }
+
+      /* send FLUSH_START event to all source pads */
+      if (flags & GST_SEEK_FLAG_FLUSH) {
+
+        GST_INFO_OBJECT (hlsdemux2, "sending flush start on all the stream pads");
+
+        for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+          GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
+
+          if (cur_stream && GST_PAD_TASK(cur_stream->pad)) {
+            gboolean bret = FALSE;
+            bret = gst_pad_push_event (cur_stream->pad, gst_event_new_flush_start ());
+            GST_DEBUG_OBJECT (cur_stream->pad, "flush_start returned = %d", bret);
+          }
+        }
+      }
+
+      /* wait till all stream pad's task paused */
+      for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+        GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
+
+        if (cur_stream && GST_PAD_TASK(cur_stream->pad)) {
+          GST_INFO_OBJECT (cur_stream->pad, "trying acquire stream lock");
+          GST_PAD_STREAM_LOCK (cur_stream->pad);
+          GST_INFO_OBJECT (cur_stream->pad, "acquired stream lock");
+          GST_PAD_STREAM_UNLOCK (cur_stream->pad);
+        }
+      }
+
+      /* pause fragment download loop */
+      g_mutex_lock (hlsdemux2->kdownloader->lock);
+      GST_INFO_OBJECT (stream->pad, "Signalling key downloader condition");
+      g_cond_signal (hlsdemux2->kdownloader->cond);
+      g_mutex_unlock (hlsdemux2->kdownloader->lock);
+
+      g_mutex_lock (hlsdemux2->fdownloader->lock);
+      GST_INFO_OBJECT (stream->pad, "Signalling fragment downloader condition");
+      g_cond_signal (hlsdemux2->fdownloader->cond);
+      g_mutex_unlock (hlsdemux2->fdownloader->lock);
+
+      g_mutex_lock (hlsdemux2->pldownloader->lock);
+      GST_INFO_OBJECT (stream->pad, "Signalling playlist downloader condition");
+      g_cond_signal (hlsdemux2->pldownloader->cond);
+      g_mutex_unlock (hlsdemux2->pldownloader->lock);
+
+      GST_INFO_OBJECT (stream->pad, "waiting for download task to pause...");
+      g_static_rec_mutex_lock (&hlsdemux2->download_lock);
+      g_static_rec_mutex_unlock (&hlsdemux2->download_lock);
+
+      GST_INFO_OBJECT (hlsdemux2, "Download task paused");
+
+      /* clear internal stream queues */
+      for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+        GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
+
+        if (cur_stream && cur_stream->queue) {
+          while (!g_queue_is_empty (cur_stream->queue)) {
+            gpointer data = NULL;
+            data = g_queue_pop_head (cur_stream->queue);
+            gst_object_unref (data);
+          }
+          g_queue_clear (cur_stream->queue);
+          cur_stream->cached_duration = 0;
+          stream->percent = 0;
+
+          while (!g_queue_is_empty (cur_stream->downloader_queue)) {
+            gpointer data = NULL;
+            data = g_queue_pop_head (cur_stream->downloader_queue);
+            gst_object_unref (data);
+          }
+          g_queue_clear (cur_stream->downloader_queue);
+        }
+      }
+
+#if 0 /* useful when we want to switch to lowest variant on seek for faster buffering */
+      if (gst_m3u8_client_has_variant_playlist (hlsdemux2->client)) {
+        /* intentionally sending zero download rate, to move to least possible variant */
+        gst_hlsdemux2_change_playlist (hlsdemux2, 0, NULL);
+      }
+#endif
+
+      /* send FLUSH_STOP event to all source pads */
+      if (flags & GST_SEEK_FLAG_FLUSH) {
+
+        GST_INFO_OBJECT (hlsdemux2, "sending flush stop");
+
+        for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+          GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
+
+          if (cur_stream && GST_PAD_TASK(cur_stream->pad)) {
+            gboolean bret = FALSE;
+            bret = gst_pad_push_event (cur_stream->pad, gst_event_new_flush_stop ());
+            GST_DEBUG_OBJECT (cur_stream->pad, "flush_stop returned = %d", bret);
+          }
+        }
+      }
+
+      hlsdemux2->flushing = FALSE;
+      hlsdemux2->fdownloader->find_mediaseq = TRUE;
+      hlsdemux2->fdownloader->seeked_pos = start;
+
+      /* start all streams loop tasks & fragment download task */
+      for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+        GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
+
+        if (cur_stream && GST_PAD_TASK(cur_stream->pad)) {
+          GST_INFO_OBJECT (cur_stream->pad, "Starting push task");
+          cur_stream->need_newsegment = TRUE;
+          cur_stream->nts = GST_CLOCK_TIME_NONE; /*useful for audio-only seeking */
+          cur_stream->cdisc = 0;
+          cur_stream->fts = GST_CLOCK_TIME_NONE;
+          cur_stream->valid_fts_rcvd = FALSE;
+          cur_stream->total_stream_time = 0;
+
+          if (!gst_pad_start_task (cur_stream->pad, (GstTaskFunction) gst_hlsdemux2_push_loop, cur_stream)) {
+            GST_ERROR_OBJECT (hlsdemux2, "failed to start stream task...");
+            GST_ELEMENT_ERROR (hlsdemux2, RESOURCE, FAILED, ("failed to create stream push loop"), (NULL));
+            goto error;
+          }
+        }
+      }
+
+      gst_hlsdemux2_apply_disc (hlsdemux2);
+
+      GST_INFO_OBJECT (hlsdemux2, "Starting Download task..");
+
+      gst_task_start (hlsdemux2->download_task);
+
+      GST_INFO_OBJECT (hlsdemux2, "Successfully configured SEEK...");
+      gst_event_unref (event);
+      return TRUE;
+    }
+    default:
+      break;
+  }
+
+  return gst_pad_event_default (pad, event);
+
+error:
+  GST_ERROR_OBJECT (hlsdemux2, "seeking failed...");
+  gst_event_unref (event);
+  return FALSE;
+}
+
+static gboolean
+gst_hlsdemux2_src_query (GstPad *pad, GstQuery * query)
+{
+  GstHLSDemux2 *hlsdemux2 = NULL;
+  gboolean ret = FALSE;
+  GstHLSDemux2Stream *stream = NULL;
+
+  if (query == NULL)
+    return FALSE;
+
+  stream = (GstHLSDemux2Stream *) (gst_pad_get_element_private (pad));
+  hlsdemux2 = stream->parent;
+
+  switch (query->type) {
+    case GST_QUERY_DURATION:{
+      GstClockTime duration = -1;
+      GstFormat fmt;
+
+      gst_query_parse_duration (query, &fmt, NULL);
+      if (fmt == GST_FORMAT_TIME) {
+        duration = gst_m3u8_client_get_duration (hlsdemux2->client);
+        if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0) {
+          gst_query_set_duration (query, GST_FORMAT_TIME, duration);
+          ret = TRUE;
+        }
+      }
+      GST_LOG_OBJECT (hlsdemux2, "GST_QUERY_DURATION returns %s with duration %"
+          GST_TIME_FORMAT, ret ? "TRUE" : "FALSE", GST_TIME_ARGS (duration));
+      break;
+    }
+    case GST_QUERY_URI:
+      if (hlsdemux2->client) {
+        /* FIXME: Do we answer with the variant playlist, with the current
+         * playlist or the the uri of the least downlowaded fragment? */
+        gst_query_set_uri (query, gst_m3u8_client_get_uri (hlsdemux2->client));
+        ret = TRUE;
+      }
+      break;
+    case GST_QUERY_SEEKING:{
+      GstFormat fmt;
+      gint64 stop = -1;
+
+      gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
+      GST_INFO_OBJECT (hlsdemux2, "Received GST_QUERY_SEEKING with format %d",
+          fmt);
+      if (fmt == GST_FORMAT_TIME) {
+        GstClockTime duration;
+
+        duration = gst_m3u8_client_get_duration (hlsdemux2->client);
+        if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0)
+          stop = duration;
+
+        gst_query_set_seeking (query, fmt,
+            !gst_m3u8_client_is_live (hlsdemux2->client), 0, stop);
+        ret = TRUE;
+        GST_INFO_OBJECT (hlsdemux2, "GST_QUERY_SEEKING returning with stop : %"
+            GST_TIME_FORMAT, GST_TIME_ARGS (stop));
+      }
+      break;
+    }
+    default:
+      /* Don't fordward queries upstream because of the special nature of this
+       * "demuxer", which relies on the upstream element only to be fed with the
+       * first playlist */
+      break;
+  }
+
+  return ret;
+}
+
+static gchar *
+gst_hlsdemux2_uri_get_domain ( GstHLSDemux2 *demux, gchar * uri)
+{
+  gchar *pointer = uri;
+  gchar *domain = NULL;
+  guint flag = 0;
+  guint counter=0;
+
+  domain = g_malloc0(strlen (uri));
+  if (!domain) {
+    GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
+    GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
+    return NULL;
+  }
+
+  while(*pointer != '\0') {
+    switch(*pointer) {
+      case '.':
+        flag = 1;
+        break;
+      case '/':
+        if(flag==1)
+          flag = 2;
+        break;
+    }
+    if(flag==1) {
+      domain[counter]=*pointer;
+      counter++;
+    } else if(flag == 2) {
+      domain[counter]='\0';
+      break;
+    }
+    pointer++;
+  }
+
+  GST_DEBUG_OBJECT (demux, "uri = %s and domain = %s", uri, domain);
+  return domain;
+}
+
+static void
+gst_hlsdemux2_get_cookies(GstHLSDemux2 *demux)
+{
+  GstQuery *cquery;
+  GstStructure *structure;
+  gboolean bret = FALSE;
+
+  structure = gst_structure_new ("HTTPCookies",
+                                 "cookies", G_TYPE_STRING, NULL, NULL);
+
+  cquery = gst_query_new_application (GST_QUERY_CUSTOM, structure);
+
+  bret = gst_pad_peer_query (demux->sinkpad, cquery);
+  if (bret) {
+    const GstStructure *s;
+    const GValue *value;
+
+    s = gst_query_get_structure (cquery);
+    value = gst_structure_get_value (s, "cookies");
+    demux->playlistCookie = g_strdupv (g_value_get_boxed (value));
+
+    GST_INFO_OBJECT (demux, "Received playlist cookies from upstream element : %s", demux->playlistCookie ? *(demux->playlistCookie) : NULL);
+    if(demux->playlistCookie){
+        demux->lastCookie = g_strdupv(demux->playlistCookie);
+    }
+  } else {
+    GST_WARNING_OBJECT (demux, "Failed to get cookies");
+  }
+
+  gst_query_unref (cquery);
+}
+
+static void
+gst_hlsdemux2_get_user_agent(GstHLSDemux2 *demux)
+{
+  GstQuery *cquery;
+  GstStructure *structure;
+  gboolean bret = FALSE;
+
+  structure = gst_structure_new ("HTTPUserAgent",
+                                 "user-agent", G_TYPE_STRING, NULL, NULL);
+
+  cquery = gst_query_new_application (GST_QUERY_CUSTOM, structure);
+
+  bret = gst_pad_peer_query (demux->sinkpad, cquery);
+  if (bret) {
+    const GstStructure *s;
+    const GValue *value;
+
+    GST_INFO_OBJECT (demux, "Received user-agent from upstream element...");
+
+    s = gst_query_get_structure (cquery);
+    value = gst_structure_get_value (s, "user-agent");
+    demux->user_agent = g_strdup (g_value_get_string (value));
+
+    GST_INFO_OBJECT (demux,"User agent received from query : %s", demux->user_agent);
+  } else {
+    GST_WARNING_OBJECT (demux, "Failed to get user-agent");
+  }
+
+  gst_query_unref (cquery);
+}
+
+static gboolean
+gst_hlsdemux2_create_playlist_download (GstHLSDemux2 *demux, const gchar *playlist_uri)
+{
+  if (!gst_uri_is_valid (playlist_uri)) {
+    GST_ERROR_OBJECT (demux, "invalid uri : %s...", playlist_uri == NULL ? "NULL" : playlist_uri);
+    return FALSE;
+  }
+
+  if (demux->cancelled || demux->flushing) {
+    GST_WARNING_OBJECT (demux,"returning from download playlist due to cancel or flushing..");
+    return FALSE;
+  }
+
+  /* create playlist downloader pipeline */
+  demux->pldownloader->pipe = gst_pipeline_new ("playlist-downloader");
+  if (!demux->pldownloader->pipe) {
+    GST_ERROR_OBJECT (demux, "failed to create pipeline");
+    return FALSE;
+  }
+
+  demux->pldownloader->bus = gst_pipeline_get_bus (GST_PIPELINE (demux->pldownloader->pipe));
+  gst_bus_set_sync_handler(demux->pldownloader->bus, gst_hlsdemux2_playlist_download_bus_sync_cb, demux);
+
+  gst_object_unref (demux->pldownloader->bus);
+
+  GST_INFO_OBJECT (demux, "Creating source element for the URI : %s", playlist_uri);
+
+  /* creating source element */
+  demux->pldownloader->urisrc = gst_element_make_from_uri (GST_URI_SRC, playlist_uri, "playlisturisrc");
+  if (!demux->pldownloader->urisrc) {
+    GST_ERROR_OBJECT (demux, "failed to create urisrc");
+    return FALSE;
+  }
+  g_object_set (G_OBJECT (demux->pldownloader->urisrc), "timeout", HLSDEMUX2_HTTP_TIMEOUT, NULL);
+  g_object_set (G_OBJECT (demux->pldownloader->urisrc), "user-agent", demux->user_agent, NULL);
+  g_object_set (G_OBJECT (demux->pldownloader->urisrc), "ahs-streaming", TRUE, NULL);
+
+  demux->playlistDomain = gst_hlsdemux2_uri_get_domain(demux, playlist_uri);
+  if(!g_strcmp0(demux->playlistDomain, demux->lastDomain) && demux->lastCookie) {
+    g_strfreev (demux->playlistCookie);
+    demux->playlistCookie = g_strdupv (demux->lastCookie);
+  }
+
+  if (demux->playlistCookie) {
+    GST_DEBUG_OBJECT (demux, "Setting cookies before PLAYLIST download, before PLAYING: %s", *(demux->playlistCookie));
+    /* setting cookies */
+    g_object_set (demux->pldownloader->urisrc, "cookies", demux->playlistCookie, NULL);
+  }
+
+  /* create sink element */
+  demux->pldownloader->sink =  gst_element_factory_make ("appsink", "playlistsink");
+  if (!demux->pldownloader->sink) {
+    GST_ERROR_OBJECT (demux, "failed to create playlist sink element");
+    return FALSE;
+  }
+  g_object_set (G_OBJECT (demux->pldownloader->sink), "sync", FALSE, "emit-signals", TRUE, NULL);
+  g_signal_connect (demux->pldownloader->sink, "new-buffer",  G_CALLBACK (gst_hlsdemux2_on_playlist_buffer), demux);
+
+  gst_bin_add_many (GST_BIN (demux->pldownloader->pipe), demux->pldownloader->urisrc, demux->pldownloader->sink, NULL);
+
+  if (!gst_element_link_many (demux->pldownloader->urisrc, demux->pldownloader->sink, NULL)) {
+    GST_ERROR_OBJECT (demux, "failed to link src & demux elements...");
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static void
+gst_hlsdemux2_destroy_playlist_download (GstHLSDemux2 * demux)
+{
+  if (demux->pldownloader->pipe) {
+    GST_DEBUG_OBJECT (demux, "Shutting down playlist download pipeline");
+    gst_element_set_state (demux->pldownloader->pipe, GST_STATE_NULL);
+    gst_element_get_state (demux->pldownloader->pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+    gst_object_unref (demux->pldownloader->pipe);
+    demux->pldownloader->pipe = NULL;
+  }
+}
+
+static gboolean
+gst_hlsdemux2_download_playlist (GstHLSDemux2 *demux, const gchar * uri)
+{
+  GstStateChangeReturn ret;
+
+  if (demux->playlist_uri) {
+    g_free (demux->playlist_uri);
+  }
+  demux->playlist_uri = g_strdup (uri);
+
+  demux->pldownloader->download_start_ts = gst_util_get_timestamp();
+
+  if (!gst_hlsdemux2_create_playlist_download (demux, uri)) {
+    GST_ERROR_OBJECT (demux, "failed to create playlist download pipeline");
+    return FALSE;
+  }
+
+  ret = gst_element_set_state (demux->pldownloader->pipe, GST_STATE_PLAYING);
+  if (ret == GST_STATE_CHANGE_FAILURE) {
+    GST_ERROR_OBJECT (demux, "set_state failed...");
+    return FALSE;
+  }
+
+  /* schedule the next update of playlist */
+  if (demux->is_live)
+    gst_hlsdemux2_schedule (demux);
+
+  /* wait until:
+   *   - the download succeed (EOS)
+   *   - the download failed (Error message on the fetcher bus)
+   *   - the download was canceled
+   */
+  GST_LOG_OBJECT (demux, "Waiting to fetch the URI");
+  g_cond_wait (demux->pldownloader->cond, demux->pldownloader->lock);
+  GST_LOG_OBJECT (demux, "Recived signal to shutdown...");
+
+  if (demux->playlistCookie)
+    g_strfreev (demux->playlistCookie);
+
+  g_object_get (demux->pldownloader->urisrc, "cookies", &demux->playlistCookie, NULL);
+
+  GST_DEBUG_OBJECT (demux, "Got cookies after PLAYLIST download : %s", demux->playlistCookie ? *(demux->playlistCookie) : NULL);
+
+  if(demux->playlistCookie){
+    g_strfreev(demux->lastCookie);
+    g_free(demux->lastDomain);
+    demux->lastCookie = g_strdupv(demux->playlistCookie);
+    demux->lastDomain = g_strdup(demux->playlistDomain);
+  }
+
+  gst_hlsdemux2_destroy_playlist_download (demux);
+
+  if (demux->cancelled || demux->flushing)
+    return FALSE;
+
+  return TRUE;
+}
+
+
+static gboolean
+gst_hlsdemux2_update_playlist (GstHLSDemux2 * demux, gboolean update, gboolean *is_error)
+{
+  gchar *playlist = NULL;
+  gboolean updated = FALSE;
+  const gchar *playlist_uri = gst_m3u8_client_get_current_uri (demux->client);
+
+  *is_error = FALSE;
+
+  if (!gst_m3u8_client_is_playlist_download_needed (demux->client)) {
+    GST_INFO_OBJECT (demux, "Playlist download is not needed...");
+    return TRUE;
+  }
+
+  g_mutex_lock (demux->pldownloader->lock);
+
+try_again:
+
+  if (!gst_hlsdemux2_download_playlist (demux, playlist_uri)) {
+    GST_ERROR_OBJECT (demux, "failed to create playlist download");
+    goto error;
+  }
+
+  if ((demux->pldownloader->playlist == NULL) || (GST_BUFFER_DATA(demux->pldownloader->playlist) == NULL)) {
+    // TODO: don't exact reason, why eos is coming from soup without data...
+    GST_ERROR_OBJECT (demux, "Received playlist eos, without playlist data -> TRY AGAIN");
+    goto try_again;
+  }
+
+  /* reset the count */
+  demux->soup_request_fail_cnt = HLSDEMUX2_SOUP_FAILED_CNT;
+
+  playlist = gst_hlsdemux2_src_buf_to_utf8_playlist (demux->pldownloader->playlist);
+  if (!playlist) {
+    GST_ERROR_OBJECT(demux, "failed to create playlist");
+    goto error;
+  }
+  demux->pldownloader->playlist = NULL;
+
+  updated = gst_m3u8_client_update (demux->client, playlist);
+  g_mutex_unlock (demux->pldownloader->lock);
+
+  return updated;
+
+error:
+  if (demux->flushing)
+    *is_error = TRUE;
+  g_mutex_unlock (demux->pldownloader->lock);
+  return FALSE;
+}
+
+static gboolean
+gst_hlsdemux2_create_key_download (GstHLSDemux2 *demux, const gchar *key_uri)
+{
+  if (!gst_uri_is_valid (key_uri)) {
+    GST_ERROR_OBJECT (demux, "invalid uri : %s...", key_uri == NULL ? "NULL" : key_uri);
+    return FALSE;
+  }
+
+  if (demux->cancelled || demux->flushing) {
+    GST_WARNING_OBJECT (demux,"returning from download key due to cancel or flushing..");
+    return FALSE;
+  }
+
+  demux->kdownloader->pipe = gst_pipeline_new ("keydownloader");
+  if (!demux->kdownloader->pipe) {
+    GST_ERROR_OBJECT (demux, "failed to create pipeline");
+    return FALSE;
+  }
+
+  demux->kdownloader->bus = gst_pipeline_get_bus (GST_PIPELINE (demux->kdownloader->pipe));
+  gst_bus_add_watch (demux->kdownloader->bus, (GstBusFunc)gst_hlsdemux2_key_download_bus_cb, demux);
+  gst_object_unref (demux->kdownloader->bus);
+
+  GST_INFO_OBJECT (demux, "Creating source element for the URI : %s", key_uri);
+
+  demux->kdownloader->urisrc = gst_element_make_from_uri (GST_URI_SRC, key_uri, "keyurisrc");
+  if (!demux->kdownloader->urisrc) {
+    GST_ERROR_OBJECT (demux, "failed to create urisrc");
+    return FALSE;
+  }
+
+  g_object_set (G_OBJECT (demux->kdownloader->urisrc), "timeout", HLSDEMUX2_HTTP_TIMEOUT, NULL);
+  g_object_set (G_OBJECT (demux->kdownloader->urisrc), "user-agent", demux->user_agent, NULL);
+  g_object_set (G_OBJECT (demux->kdownloader->urisrc), "ahs-streaming", TRUE, NULL);
+
+  demux->keyDomain = gst_hlsdemux2_uri_get_domain(demux, key_uri);
+  if(!g_strcmp0(demux->keyDomain, demux->lastDomain) && demux->lastCookie) {
+    g_strfreev(demux->keyCookie);
+    demux->keyCookie = g_strdupv(demux->lastCookie);
+  }
+
+  if (demux->keyCookie) {
+    GST_DEBUG_OBJECT (demux, "Setting cookies before KEY download goto PLAYING : %s", *(demux->keyCookie));
+    g_object_set (demux->kdownloader->urisrc, "cookies", demux->keyCookie, NULL);
+  }
+
+  demux->kdownloader->sink =  gst_element_factory_make ("appsink", "keyfilesink");
+  if (!demux->kdownloader->sink) {
+    GST_ERROR_OBJECT (demux, "failed to create playlist sink element");
+    return FALSE;
+  }
+  g_object_set (G_OBJECT (demux->kdownloader->sink), "sync", FALSE, "emit-signals", TRUE, NULL);
+  g_signal_connect (demux->kdownloader->sink, "new-buffer",  G_CALLBACK (gst_hlsdemux2_on_key_buffer), demux);
+
+  gst_bin_add_many (GST_BIN (demux->kdownloader->pipe), demux->kdownloader->urisrc, demux->kdownloader->sink, NULL);
+
+  if (!gst_element_link_many (demux->kdownloader->urisrc, demux->kdownloader->sink, NULL)) {
+    GST_ERROR_OBJECT (demux, "failed to link src & demux elements...");
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static void
+gst_hlsdemux2_destroy_key_download (GstHLSDemux2 * demux)
+{
+  if (demux->kdownloader->pipe) {
+    GST_DEBUG_OBJECT (demux, "Shutting down key download pipeline");
+    gst_element_set_state (demux->kdownloader->pipe, GST_STATE_NULL);
+    gst_element_get_state (demux->kdownloader->pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+    gst_object_unref (demux->kdownloader->pipe);
+    demux->kdownloader->pipe = NULL;
+  }
+}
+
+static gboolean
+gst_hlsdemux2_download_key (GstHLSDemux2 *demux, const gchar * uri)
+{
+  GstStateChangeReturn ret;
+
+  if (demux->key_uri) {
+    g_free (demux->key_uri);
+  }
+  demux->key_uri = g_strdup (uri);
+
+  g_mutex_lock (demux->kdownloader->lock);
+
+  if (!gst_hlsdemux2_create_key_download (demux, uri)) {
+    GST_ERROR_OBJECT (demux, "failed to create key download pipeline");
+    return FALSE;
+  }
+
+  ret = gst_element_set_state (demux->kdownloader->pipe, GST_STATE_PLAYING);
+  if (ret == GST_STATE_CHANGE_FAILURE) {
+    GST_ERROR_OBJECT (demux, "set_state failed...");
+    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 key URI");
+  g_cond_wait (demux->kdownloader->cond, demux->kdownloader->lock);
+  GST_DEBUG_OBJECT (demux, "Recived signal to shutdown key downloader...");
+  g_mutex_unlock (demux->kdownloader->lock);
+
+  if (demux->keyCookie) {
+    g_object_get (demux->kdownloader->urisrc, "cookies", &demux->keyCookie, NULL);
+  }
+
+  GST_DEBUG_OBJECT (demux, "Got cookies after KEY download : %s", demux->keyCookie ? *(demux->keyCookie) : NULL);
+
+  if(demux->keyCookie){
+      g_strfreev(demux->lastCookie);
+      g_free(demux->lastDomain);
+      demux->lastCookie = g_strdupv(demux->keyCookie);
+      demux->lastDomain = g_strdup(demux->keyDomain);
+  }
+
+  gst_hlsdemux2_destroy_key_download (demux);
+
+  if (demux->cancelled || demux->flushing)
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
+gst_hlsdemux2_have_type_cb (GstElement * typefind, guint probability,
+    GstCaps * caps, GstHLSDemux2 * demux)
+{
+  GstStructure *structure = NULL;
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  GST_DEBUG_OBJECT (demux, "typefind found caps %" GST_PTR_FORMAT, caps);
+
+  if (gst_structure_has_name (structure, "video/mpegts")) {
+    /* found ts fragment */
+    demux->fdownloader->demuxer = gst_element_factory_make ("mpegtsdemux", "tsdemux");
+    if (!demux->fdownloader->demuxer) {
+      GST_ERROR_OBJECT (demux, "failed to create mpegtsdemux element");
+      GST_ELEMENT_ERROR (demux, CORE, MISSING_PLUGIN, ("failed to create mpegtsdemuxer element"), (NULL));
+      return;
+    }
+    g_signal_connect (demux->fdownloader->demuxer, "pad-added", G_CALLBACK (gst_hlsdemux2_new_pad_added), demux);
+
+    gst_bin_add (GST_BIN (demux->fdownloader->pipe), demux->fdownloader->demuxer);
+
+    /* set queue element to PLAYING state */
+    gst_element_set_state (demux->fdownloader->demuxer, GST_STATE_PLAYING);
+
+    if (!gst_element_link (demux->fdownloader->typefind, demux->fdownloader->demuxer)) {
+      GST_ERROR_OBJECT (demux, "failed to link src and demux elements...");
+      GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("failed to link typefind & demuxer"), (NULL));
+      return;
+    }
+  } else if (gst_structure_has_name (structure, "application/x-id3")) {
+    /* found ts fragment */
+    demux->fdownloader->demuxer = gst_element_factory_make ("id3demux", "id3demuxer");
+    if (!demux->fdownloader->demuxer) {
+      GST_ERROR_OBJECT (demux, "failed to create mpegtsdemux element");
+      GST_ELEMENT_ERROR (demux, CORE, MISSING_PLUGIN, ("failed to create id3demuxer element"), (NULL));
+      return;
+    }
+    g_signal_connect (demux->fdownloader->demuxer, "pad-added", G_CALLBACK (gst_hlsdemux2_new_pad_added), demux);
+
+    gst_bin_add (GST_BIN (demux->fdownloader->pipe), demux->fdownloader->demuxer);
+
+    /* set queue element to PLAYING state */
+    gst_element_set_state (demux->fdownloader->demuxer, GST_STATE_PLAYING);
+
+    if (!gst_element_link_many (demux->fdownloader->typefind, demux->fdownloader->demuxer, NULL)) {
+      GST_ERROR_OBJECT (demux, "failed to link src and demux elements...");
+      GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("failed to link typefind & demuxer"), (NULL));
+      return;
+    }
+
+    /* as the fragment does not contain in container format, force the timestamps based on fragment duration */
+    demux->fdownloader->force_timestamps = TRUE;
+  }
+}
+
+static gboolean
+gst_hlsdemux2_download_monitor_thread (GstHLSDemux2 *demux)
+{
+  GTimeVal post_msg_update = {0, };
+
+  g_mutex_lock (demux->post_msg_lock);
+  GST_INFO_OBJECT (demux, "waiting for streaming to start to post message...");
+  g_cond_wait (demux->post_msg_start, demux->post_msg_lock);
+  GST_INFO_OBJECT (demux, "Start posting messages...");
+  g_mutex_unlock (demux->post_msg_lock);
+
+  while (TRUE) {
+    gboolean do_post = FALSE;
+    guint64 percent = 0;
+    guint idx = 0;
+    guint64 total_percent = 0;
+    gboolean bret = FALSE;
+
+    if (demux->cancelled) {
+      GST_WARNING_OBJECT (demux, "returning msg posting thread...");
+      return TRUE;
+    }
+
+    /* schedule the next update using the target duration field of the
+     * playlist */
+    post_msg_update.tv_sec = 0;
+    post_msg_update.tv_usec = 0;
+
+    g_get_current_time (&post_msg_update);
+    g_time_val_add (&post_msg_update, 200000); // posts buffering msg after every 0.5 sec
+
+    /* verify fast switch from here */
+    g_mutex_lock (demux->fdownloader->lock);
+    if (demux->fdownloader->ndownloaded
+      && !demux->fdownloader->applied_fast_switch && demux->fdownloader->download_start_ts) {
+      gst_hlsdemux2_check_fast_switch (demux);
+    }
+    g_mutex_unlock (demux->fdownloader->lock);
+
+    /* calculate avg percent of streams' percentages */
+    for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+      GstHLSDemux2Stream *stream = demux->streams[idx];
+      if (stream ) {
+        guint64 stream_percent = 0;
+
+        stream_percent = ((stream->cached_duration * 100) / (demux->total_cache_duration / DEFAULT_NUM_FRAGMENTS_CACHE));
+        GST_DEBUG_OBJECT (stream->pad, "stream percent = %"G_GUINT64_FORMAT, stream_percent);
+        total_percent += stream_percent;
+      }
+    }
+    percent = total_percent / demux->active_stream_cnt;
+
+    if (demux->is_buffering) {
+      do_post = TRUE;
+      if (percent >= 100)
+        demux->is_buffering = FALSE;
+    } else {
+      if (percent < 10) {
+        /* if buffering drops below 10% lets start posting msgs */
+        demux->is_buffering = TRUE;
+        do_post = TRUE;
+      }
+    }
+
+    if (do_post) {
+      GstMessage *message;
+
+      if (percent > 100) {
+        //GST_LOG_OBJECT (demux, " exceeded percent = %d", (gint) percent);
+        percent = 100;
+      }
+
+      if (demux->end_of_playlist) {
+        GST_INFO_OBJECT (demux, "end of the playlist reached... always post 100%");
+        percent = 100;
+      }
+
+      if (percent != demux->percent) {
+        g_mutex_lock (demux->buffering_lock);
+        demux->percent = percent;
+        g_mutex_unlock (demux->buffering_lock);
+
+        GST_LOG_OBJECT (demux, "buffering %d percent", (gint) percent);
+
+        /* posting buffering to internal bus, which will take average & post to main bus */
+        message = gst_message_new_buffering (GST_OBJECT_CAST (demux), (gint) demux->percent);
+        if (!gst_element_post_message (GST_ELEMENT_CAST (demux), message)) {
+          GST_WARNING_OBJECT (demux, "failed to post buffering msg...");
+        }
+      }
+    }
+
+    g_mutex_lock (demux->post_msg_lock);
+    /*  block until the next scheduled update or the exit signal */
+    bret = g_cond_timed_wait (demux->post_msg_exit, demux->post_msg_lock, &post_msg_update);
+    g_mutex_unlock (demux->post_msg_lock);
+
+    if (bret) {
+      GST_WARNING_OBJECT (demux, "signalled to exit posting msgs...");
+      break;
+    }
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_hlsdemux2_fragurisrc_event_handler (GstPad * pad, GstEvent *event, gpointer data)
+{
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
+
+  if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
+    GTimeVal time = {0, };
+
+    GST_INFO_OBJECT (demux, "received EOS from fragment downloader's httpsrc");
+
+    if (demux->fdownloader->error_rcvd) {
+      GST_WARNING_OBJECT (demux, "received EOS event after ERROR.. discard this");
+      demux->fdownloader->src_downloaded_size = 0;
+      demux->fdownloader->download_stop_ts = demux->fdownloader->download_start_ts = 0;
+      return FALSE;
+    }
+
+    /* download rate calculation : note down stop time*/
+    g_get_current_time (&time);
+    demux->fdownloader->download_stop_ts = gst_util_get_timestamp();
+
+    GST_INFO_OBJECT (demux, "download stop_ts = %"G_GUINT64_FORMAT, demux->fdownloader->download_stop_ts);
+    GST_INFO_OBJECT (demux, "time taken to download current fragment = %"G_GUINT64_FORMAT, demux->fdownloader->download_stop_ts - demux->fdownloader->download_start_ts);
+    GST_INFO_OBJECT (demux, "fragment downloaded size = %"G_GUINT64_FORMAT" and content_size = %"G_GUINT64_FORMAT,
+      demux->fdownloader->src_downloaded_size, demux->fdownloader->content_size);
+
+    if (demux->fdownloader->src_downloaded_size && (demux->fdownloader->src_downloaded_size == demux->fdownloader->content_size)) {
+      guint64 download_rate = 0;
+      guint i = 0;
+      guint64 dsum = 0;
+
+      /* calculate current fragment download rate */
+      download_rate = (demux->fdownloader->src_downloaded_size * 8 * GST_SECOND) /
+        (demux->fdownloader->download_stop_ts - demux->fdownloader->download_start_ts);
+
+      if (demux->fdownloader->avg_frag_drates->len == HLSDEMUX2_MAX_N_PAST_FRAG_DOWNLOADRATES) {
+        /* removing starting element */
+        g_array_remove_index (demux->fdownloader->avg_frag_drates, 0);
+        GST_DEBUG_OBJECT (demux, "removing index from download rates");
+      }
+      g_array_append_val (demux->fdownloader->avg_frag_drates, download_rate);
+
+      for (i = 0 ; i < demux->fdownloader->avg_frag_drates->len; i++) {
+        dsum += g_array_index (demux->fdownloader->avg_frag_drates, guint64, i);
+      }
+
+      demux->fdownloader->download_rate = dsum / demux->fdownloader->avg_frag_drates->len;
+
+      GST_INFO_OBJECT (demux, " >>>> DOWNLOAD RATE = %"G_GUINT64_FORMAT, demux->fdownloader->download_rate);
+    } else {
+      GST_WARNING_OBJECT (demux, "something wrong better not to calculate download rate with this and discard EOS...");
+      demux->fdownloader->src_downloaded_size = 0;
+      demux->fdownloader->download_stop_ts = demux->fdownloader->download_start_ts = 0;
+      return FALSE;
+    }
+
+    demux->fdownloader->src_downloaded_size = 0;
+    demux->fdownloader->download_stop_ts = demux->fdownloader->download_start_ts = 0;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_hlsdemux2_check_fast_switch (GstHLSDemux2 *demux)
+{
+  GstClockTime elapsed_time = 0;
+  guint i = 0;
+  guint64 download_rate = 0;
+
+  elapsed_time = gst_util_get_timestamp();
+
+  if (gst_m3u8_client_has_variant_playlist (demux->client) &&
+    ((elapsed_time - demux->fdownloader->download_start_ts) >
+      (HLSDEMUX2_FAST_CHECK_WARNING_TIME_FACTOR * demux->target_duration))) {
+    guint64 drate_sum = 0;
+    GList *previous_variant, *current_variant;
+    gint old_bandwidth, new_bandwidth;
+
+    GST_INFO_OBJECT (demux, "Doing fast switch using array len %d...", demux->fdownloader->avg_chunk_drates->len);
+
+    for (i = 0 ; i < demux->fdownloader->avg_chunk_drates->len; i++) {
+      drate_sum += g_array_index (demux->fdownloader->avg_chunk_drates, guint64, i);
+    }
+
+    /* 0.9 factor is for compensating for connection time*/
+    download_rate = (drate_sum * 0.9) / demux->fdownloader->avg_chunk_drates->len;
+
+    GST_INFO_OBJECT (demux, "average chunk download rate = %"G_GUINT64_FORMAT, download_rate);
+
+    if ((elapsed_time - demux->fdownloader->download_start_ts) >
+      (HLSDEMUX2_FAST_CHECK_CRITICAL_TIME_FACTOR * demux->target_duration)) {
+      GST_WARNING_OBJECT (demux, "Reached FAST_SWITCH critical point...do fast_switch");
+      goto fast_switch;
+    }
+
+    previous_variant = demux->client->main->current_variant;
+    current_variant = gst_m3u8_client_get_playlist_for_bitrate (demux->client, download_rate);
+
+    old_bandwidth = GST_M3U8 (previous_variant->data)->bandwidth;
+    new_bandwidth = GST_M3U8 (current_variant->data)->bandwidth;
+
+    GST_INFO_OBJECT (demux, "variant's bandwidth got using average chunk download rate is %d", new_bandwidth);
+
+    /* Don't do anything else if the playlist is the same */
+    if (new_bandwidth == old_bandwidth) {
+      GST_WARNING_OBJECT (demux, "Either BW is recovering or NO LOWER variant available than current, DON'T DO FAST_SWITCH...");
+      return TRUE;
+    }
+
+    GST_WARNING_OBJECT (demux, "Going to do fast_switch due to BW problem...");
+    goto fast_switch;
+  }
+
+  return TRUE;
+
+fast_switch:
+
+  demux->fdownloader->download_rate = download_rate;
+
+  /* flush previous fragment downloads history */
+  for (i = 3; i ; --i) {
+    g_array_remove_index (demux->fdownloader->avg_frag_drates, i - 1);
+  }
+
+  GST_INFO_OBJECT (demux, "in fast download rate : len %d...", demux->fdownloader->avg_frag_drates->len);
+  g_array_append_val (demux->fdownloader->avg_frag_drates, demux->fdownloader->download_rate);
+
+  GST_INFO_OBJECT (demux, " >>>> DOWNLOAD RATE in fast switch = %"G_GUINT64_FORMAT, demux->fdownloader->download_rate);
+
+  demux->fdownloader->applied_fast_switch = TRUE;
+
+  /* close current fragment */
+  g_cond_signal (demux->fdownloader->cond);
+
+  return FALSE;
+
+}
+
+static gboolean
+gst_hlsdemux2_fragurisrc_buffer_handler (GstPad * pad, GstBuffer *buffer, gpointer data)
+{
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
+  GstClockTime elapsed_ts = 0;
+  guint64 chunk_drate = 0;
+
+  /* if block_switch already enabled no need to cross check. IMP check*/
+  if (demux->fdownloader->applied_fast_switch) {
+    GST_WARNING_OBJECT (demux, "already applied fast_switch.. drop current buffer");
+    return FALSE;
+  }
+
+  demux->fdownloader->src_downloaded_size += GST_BUFFER_SIZE(buffer);
+
+  if (demux->fdownloader->first_buffer) {
+    /* get the content size for doing last buffer decryption & for vaidating complete download happend or not */
+    GST_INFO_OBJECT (demux, "just received first buffer...");
+    g_object_get (demux->fdownloader->urisrc, "content-size", &demux->fdownloader->content_size, NULL);
+    GST_INFO_OBJECT (demux, "content size = %"G_GUINT64_FORMAT, demux->fdownloader->content_size);
+    demux->fdownloader->first_buffer = FALSE;
+    demux->fdownloader->chunk_start_ts = gst_util_get_timestamp();
+    demux->fdownloader->chunk_downloaded_size = 0;
+  }
+
+
+  demux->fdownloader->chunk_downloaded_size += GST_BUFFER_SIZE(buffer);
+  elapsed_ts = gst_util_get_timestamp();
+
+  if ((elapsed_ts - demux->fdownloader->chunk_start_ts) > HLSDEMUX2_CHUNK_TIME_DURATION) {
+    GST_DEBUG_OBJECT (demux, "chunk downloaded time = %"GST_TIME_FORMAT,
+      GST_TIME_ARGS(elapsed_ts - demux->fdownloader->chunk_start_ts));
+
+    chunk_drate = (demux->fdownloader->chunk_downloaded_size * 8 * GST_SECOND) / (elapsed_ts - demux->fdownloader->chunk_start_ts);
+    demux->fdownloader->chunk_start_ts = elapsed_ts;
+    demux->fdownloader->chunk_downloaded_size = 0;
+
+    GST_DEBUG_OBJECT(demux, "CHUNK DOWNLOAD RATE = %"G_GUINT64_FORMAT, chunk_drate);
+
+    if (demux->fdownloader->avg_chunk_drates->len == HLSDEMUX2_NUM_CHUNK_DOWNLOADS_FAST_SWITCH) {
+      /* removing starting element */
+      g_array_remove_index (demux->fdownloader->avg_chunk_drates, 0);
+    }
+    g_array_append_val (demux->fdownloader->avg_chunk_drates, chunk_drate);
+  }
+
+  GST_LOG_OBJECT (demux, "fragment downloaded size at urisrc = %"G_GUINT64_FORMAT, demux->fdownloader->src_downloaded_size);
+
+  return TRUE;
+}
+
+static gboolean
+gst_hlsdemux2_queue_buffer_handler (GstPad *pad, GstBuffer *buffer, gpointer data)
+{
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
+  unsigned char *encry_data = NULL;
+  unsigned char *outdata = NULL;
+  unsigned char *remained_data = NULL;
+  unsigned char* total_data = NULL;
+
+  demux->fdownloader->queue_downloaded_size += GST_BUFFER_SIZE(buffer);
+
+  GST_DEBUG_OBJECT (demux, "total downloaded size = %"G_GUINT64_FORMAT, demux->fdownloader->queue_downloaded_size);
+
+  if (demux->fdownloader->is_encrypted) {
+    guint encry_data_size = 0;
+    unsigned char *indata = GST_BUFFER_DATA (buffer);
+    guint insize = GST_BUFFER_SIZE (buffer);
+    gint out_len = 0;
+
+    if (demux->fdownloader->remaining_data && demux->fdownloader->remaining_size) {
+      GST_LOG_OBJECT (demux, "remain size = %d..", demux->fdownloader->remaining_size);
+
+      encry_data = (unsigned char *) malloc (insize + demux->fdownloader->remaining_size);
+      if (!encry_data) {
+        GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
+        GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
+        goto error;
+      }
+
+      /* copy remaining data in previous iteration */
+      memcpy (encry_data, demux->fdownloader->remaining_data, demux->fdownloader->remaining_size);
+      /* copy input encrypted data of current iteration */
+      memcpy (encry_data + demux->fdownloader->remaining_size, indata, insize);
+
+      encry_data_size = insize + demux->fdownloader->remaining_size;
+
+      free (demux->fdownloader->remaining_data);
+      demux->fdownloader->remaining_data = NULL;
+      demux->fdownloader->remaining_size = 0;
+    } else {
+      encry_data_size = insize;
+      encry_data = indata;
+    }
+
+    demux->fdownloader->remaining_size = encry_data_size % GST_HLS_DEMUX_AES_BLOCK_SIZE;
+
+    if (demux->fdownloader->remaining_size) {
+      GST_LOG_OBJECT (demux, "Remining in current iteration = %d\n", demux->fdownloader->remaining_size);
+      demux->fdownloader->remaining_data = (gchar *) malloc (demux->fdownloader->remaining_size);
+      if ( demux->fdownloader->remaining_data == NULL) {
+        GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
+        GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
+        goto error;
+      }
+
+      /* copy remained portion to buffer */
+      memcpy (demux->fdownloader->remaining_data,
+              encry_data + encry_data_size - demux->fdownloader->remaining_size,
+              demux->fdownloader->remaining_size);
+    }
+
+    out_len = encry_data_size - demux->fdownloader->remaining_size + GST_HLS_DEMUX_AES_BLOCK_SIZE;
+    outdata = (unsigned char *) malloc (out_len);
+    if (!outdata) {
+      GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
+      GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
+      goto error;
+    }
+
+    if (!gst_m3u8_client_decrypt_update (demux->client, outdata, &out_len,
+        encry_data, encry_data_size - demux->fdownloader->remaining_size)) {
+      GST_ERROR_OBJECT (demux, "failed to decrypt...\n");
+      GST_ELEMENT_ERROR (demux, STREAM, FAILED, ("failed to decrypt"), (NULL));
+      goto error;
+    }
+
+    if (encry_data != indata) {
+      g_free (encry_data);
+      encry_data = NULL;
+    }
+
+    g_free (GST_BUFFER_MALLOCDATA(buffer));
+
+    /* decrypt the final buffer */
+    if (demux->fdownloader->queue_downloaded_size == demux->fdownloader->content_size) {
+      gint remained_size = 0;
+      gint total_len = 0;
+
+      GST_LOG_OBJECT (demux, "remained data = %p & remained size = %d", demux->fdownloader->remaining_data, demux->fdownloader->remaining_size);
+
+      remained_data =  (unsigned char *) malloc (GST_HLS_DEMUX_AES_BLOCK_SIZE);
+      if (!remained_data) {
+        GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
+        GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
+        goto error;
+      }
+      gst_m3u8_client_decrypt_final (demux->client, remained_data, &remained_size);
+      GST_LOG_OBJECT (demux,"remained size = %d\n", remained_size);
+
+      if (remained_size) {
+        total_len = out_len + remained_size;
+
+        total_data = (unsigned char *) malloc (total_len);
+        if (!total_data) {
+          GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
+          GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
+          goto error;
+        }
+
+        memcpy (total_data, outdata, out_len);
+        memcpy (total_data+out_len, remained_data, remained_size);
+
+        GST_BUFFER_MALLOCDATA(buffer) = GST_BUFFER_DATA(buffer) = total_data;
+        GST_BUFFER_SIZE(buffer) = total_len;
+        g_free (remained_data);
+        g_free (outdata);
+      } else {
+        GST_BUFFER_MALLOCDATA(buffer) = GST_BUFFER_DATA(buffer) = outdata;
+        GST_BUFFER_SIZE(buffer) = out_len;
+        g_free (remained_data);
+      }
+
+      if (!gst_m3u8_client_decrypt_deinit (demux->client)) {
+        GST_WARNING_OBJECT (demux, "decryption cleanup failed...");
+      }
+    } else {
+      GST_BUFFER_MALLOCDATA(buffer) = GST_BUFFER_DATA(buffer) = outdata;
+      GST_BUFFER_SIZE(buffer) = out_len;
+    }
+  }
+
+  return TRUE;
+
+error:
+  if (encry_data)
+    free (encry_data);
+
+  if (outdata)
+    free (outdata);
+
+  if (remained_data)
+    free (remained_data);
+
+ return FALSE;
+}
+
+static gboolean
+gst_hlsdemux2_create_fragment_download (GstHLSDemux2 * demux, const gchar * uri)
+{
+  GstBus *bus = NULL;
+  GstPad *srcpad = NULL;
+
+  if (!gst_uri_is_valid (uri)) {
+    GST_ERROR_OBJECT (demux, "invalid uri : %s...", uri == NULL ? "NULL" : uri);
+    return FALSE;
+  }
+
+  /* re-initialize fragment variables */
+  demux->fdownloader->first_buffer = TRUE;
+  demux->fdownloader->cur_stream_cnt = 0;
+  demux->fdownloader->error_rcvd = FALSE;
+
+  demux->fdownloader->pipe = gst_pipeline_new ("frag-fdownloader");
+  if (!demux->fdownloader->pipe) {
+    GST_ERROR_OBJECT (demux, "failed to create pipeline");
+    return FALSE;
+  }
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (demux->fdownloader->pipe));
+  gst_bus_add_watch (bus, (GstBusFunc)gst_hlsdemux2_fragment_download_bus_cb, demux);
+  gst_object_unref (bus);
+
+  GST_INFO_OBJECT (demux, "Creating source element for the URI : %s", uri);
+
+  demux->fdownloader->urisrc = gst_element_make_from_uri (GST_URI_SRC, uri, "fragurisrc");
+  if (!demux->fdownloader->urisrc) {
+    GST_ERROR_OBJECT (demux, "failed to create urisrc");
+    return FALSE;
+  }
+
+  g_object_set (G_OBJECT (demux->fdownloader->urisrc), "timeout", HLSDEMUX2_HTTP_TIMEOUT, NULL);
+  g_object_set (G_OBJECT (demux->fdownloader->urisrc), "user-agent", demux->user_agent, NULL);
+  g_object_set (G_OBJECT (demux->fdownloader->urisrc), "ahs-streaming", TRUE, NULL);
+  g_object_set (G_OBJECT (demux->fdownloader->urisrc), "blocksize", DEFAULT_BLOCKSIZE, NULL);
+
+  demux->fragDomain = gst_hlsdemux2_uri_get_domain(demux, uri);
+  if(!g_strcmp0 (demux->fragDomain, demux->lastDomain) && demux->lastCookie) {
+    g_strfreev(demux->fragCookie);
+    demux->fragCookie = g_strdupv (demux->lastCookie);
+  }
+
+  if (demux->fragCookie) {
+    GST_DEBUG_OBJECT (demux, "Setting cookies before FRAG download goto PLAYING: %s", *(demux->fragCookie));
+    g_object_set (demux->fdownloader->urisrc, "cookies", demux->fragCookie, NULL);
+  }
+
+  srcpad = gst_element_get_static_pad (demux->fdownloader->urisrc, "src");
+  if (!srcpad) {
+    GST_ERROR_OBJECT (demux, "failed to get source pad from urisrc...");
+    return FALSE;
+  }
+
+  gst_pad_add_event_probe (srcpad, G_CALLBACK (gst_hlsdemux2_fragurisrc_event_handler), demux);
+  gst_pad_add_buffer_probe (srcpad, G_CALLBACK (gst_hlsdemux2_fragurisrc_buffer_handler), demux);
+
+  gst_object_unref (srcpad);
+
+  demux->fdownloader->queue = gst_element_factory_make ("queue2", "frag_queue");
+  if (!demux->fdownloader->queue) {
+    GST_ERROR_OBJECT (demux, "failed to create queue2");
+    return FALSE;
+  }
+
+  g_object_set (G_OBJECT (demux->fdownloader->queue),
+    "max-size-buffers", 0,
+    "max-size-bytes", 0,
+    "max-size-time", 0 * GST_SECOND, NULL);
+
+  srcpad = gst_element_get_static_pad (demux->fdownloader->queue, "src");
+  if (!srcpad) {
+    GST_ERROR_OBJECT (demux, "failed to get source pad from fragment queue...");
+    return FALSE;
+  }
+
+  gst_pad_add_buffer_probe (srcpad, G_CALLBACK (gst_hlsdemux2_queue_buffer_handler), demux);
+
+  demux->fdownloader->typefind = gst_element_factory_make ("typefind", "typefinder");
+  if (!demux->fdownloader->typefind) {
+    GST_ERROR_OBJECT (demux, "failed to create typefind element");
+    gst_object_unref (srcpad);
+    return FALSE;
+  }
+
+  gst_bin_add_many (GST_BIN (demux->fdownloader->pipe),
+    demux->fdownloader->urisrc, demux->fdownloader->queue, demux->fdownloader->typefind, NULL);
+
+  if (!gst_element_link_many (demux->fdownloader->urisrc,
+    demux->fdownloader->queue, demux->fdownloader->typefind, NULL)) {
+    GST_ERROR_OBJECT (demux, "failed to link src, queue & typefind elements...");
+    gst_object_unref (srcpad);
+    return FALSE;
+  }
+
+  /* typefind callback to determine file type */
+  g_signal_connect (demux->fdownloader->typefind, "have-type", G_CALLBACK (gst_hlsdemux2_have_type_cb), demux);
+
+  gst_object_unref (srcpad);
+
+  return TRUE;
+}
+
+static void
+gst_hlsdemux2_destroy_fragment_download (GstHLSDemux2 * demux)
+{
+  if (demux->fdownloader->pipe) {
+    GST_DEBUG_OBJECT (demux, "completely closing fragment downloader pipeline");
+    gst_element_set_state (demux->fdownloader->pipe, GST_STATE_NULL);
+    gst_element_get_state (demux->fdownloader->pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+    GST_DEBUG_OBJECT (demux, "completely closed fragment downloader pipeline");
+    gst_object_unref (demux->fdownloader->pipe);
+    demux->has_image_buffer = FALSE;
+    demux->fdownloader->pipe = NULL;
+    demux->fdownloader->cur_stream_cnt = 0;
+    g_list_free (demux->fdownloader->sinkbins); // all sink elements will be unreffed when pipeline is unreffed
+    demux->fdownloader->sinkbins = 0;
+  }
+}
+
+static gboolean
+gst_hlsdemux2_download_fragment (GstHLSDemux2 *demux, const gchar * uri)
+{
+  GstStateChangeReturn ret;
+
+  g_mutex_lock (demux->fdownloader->lock);
+
+  if (demux->cancelled || demux->flushing) {
+    GST_WARNING_OBJECT (demux,"returning from download fragment due to cancel or flushing..");
+    g_mutex_unlock (demux->fdownloader->lock);
+    return FALSE;
+  }
+
+  if (demux->frag_uri) {
+    g_free (demux->frag_uri);
+  }
+  demux->frag_uri = g_strdup (uri);
+
+  demux->fdownloader->get_next_frag = FALSE;
+
+  if (!gst_hlsdemux2_create_fragment_download (demux, uri)) {
+    GST_ERROR_OBJECT (demux, "failed to create download pipeline");
+    g_mutex_unlock (demux->fdownloader->lock);
+    return FALSE;
+  }
+
+  /* download rate calculation : note down start time*/
+  demux->fdownloader->download_start_ts = gst_util_get_timestamp();
+  GST_INFO_OBJECT (demux, "download start_ts = %"G_GUINT64_FORMAT, demux->fdownloader->download_start_ts);
+
+  ret = gst_element_set_state (demux->fdownloader->pipe, GST_STATE_PLAYING);
+  if (ret == GST_STATE_CHANGE_FAILURE) {
+    GST_ERROR_OBJECT (demux, "set_state failed...");
+    g_mutex_unlock (demux->fdownloader->lock);
+    return FALSE;
+  }
+  gst_element_get_state (demux->fdownloader->pipe, NULL, NULL, -1);
+
+  /* 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_cond_wait (demux->fdownloader->cond, demux->fdownloader->lock);
+  GST_INFO_OBJECT (demux, "Recived signal to shutdown...");
+
+  if (demux->fragCookie)
+    g_strfreev (demux->fragCookie);
+
+  g_object_get (demux->fdownloader->urisrc, "cookies", &demux->fragCookie, NULL);
+
+  GST_DEBUG_OBJECT (demux, "Got cookies after FRAG download : %s", demux->fragCookie ? *(demux->fragCookie) : NULL);
+
+  if (demux->fdownloader->applied_fast_switch) {
+    if (demux->fdownloader->src_downloaded_size == demux->fdownloader->content_size) {
+      /* to handle case, when both fast_switch & bus_callback signalled at same moment */
+      GST_WARNING_OBJECT (demux, "ignoring fast_switch as fragment download is completed...");
+      demux->fdownloader->applied_fast_switch = FALSE;
+    } else {
+      GST_WARNING_OBJECT (demux, "decrement the media sequence by one, due to fast_switch");
+      gst_m3u8_client_decrement_sequence (demux->client);
+    }
+  }
+
+  if (demux->cancelled || demux->flushing ||
+      demux->fdownloader->get_next_frag || demux->fdownloader->applied_fast_switch) {
+    GstBuffer *buf = NULL;
+    guint idx = 0;
+
+    /* clear stream queues if we already downloaded some data */
+    for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+      GstHLSDemux2Stream *stream = demux->streams[idx];
+      if (stream ) {
+        while (!g_queue_is_empty (stream->downloader_queue)) {
+          buf = g_queue_pop_head (stream->downloader_queue);
+          gst_buffer_unref (buf);
+        }
+        GST_LOG_OBJECT (stream->pad, "cleared stream download queue...");
+        g_queue_clear (stream->downloader_queue);
+      }
+    }
+  }
+
+  if(demux->fragCookie){
+    g_strfreev(demux->lastCookie);
+    g_free(demux->lastDomain);
+    demux->lastCookie = g_strdupv(demux->fragCookie);
+    demux->lastDomain = g_strdup(demux->fragDomain);
+  }
+
+  if(demux->active_stream_cnt == 1 && !demux->private_stream) {
+    gchar *image_header = NULL;
+    GValue codec_type = G_VALUE_INIT;
+    GValue image_data = G_VALUE_INIT;
+    GstMessage * tag_message = NULL;
+    struct stat stat_results;
+    gint iread = 0;
+    GstBuffer *image_buffer = NULL;
+    GstTagList * tag_list = gst_tag_list_new();
+    int dummy_fp = -1;
+
+    GST_INFO_OBJECT (demux, "Going to show fixed image");
+    dummy_fp = open (PREDEFINED_IMAGE_FRAME_LOCATION, O_RDONLY);
+    if (dummy_fp < 0) {
+      GST_WARNING_OBJECT (demux, "failed to open fixed image file : %s...", PREDEFINED_IMAGE_FRAME_LOCATION);
+      goto skip_posting_image;
+    }
+
+    GST_LOG_OBJECT (demux, "opened fixed image file %s successfully...", PREDEFINED_IMAGE_FRAME_LOCATION);
+
+    if (fstat (dummy_fp, &stat_results) < 0) {
+      GST_WARNING_OBJECT (demux, "failed to get stats of a file...");
+      close (dummy_fp);
+      goto skip_posting_image;
+    }
+
+    GST_LOG_OBJECT (demux, "size of the dummy file = %d", stat_results.st_size);
+
+    image_buffer = gst_buffer_new_and_alloc (stat_results.st_size);
+    if (!image_buffer) {
+      GST_ERROR_OBJECT (demux, "failed to allocate memory...");
+      GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
+      close (dummy_fp);
+      goto error;
+    }
+
+    iread = read (dummy_fp, GST_BUFFER_DATA (image_buffer), stat_results.st_size);
+
+    GST_LOG_OBJECT (demux, "read size = %d successfully", iread);
+
+    close (dummy_fp);
+
+    /* check whether it is same as previous image */
+    if (demux->prev_image_buffer &&
+      (GST_BUFFER_SIZE(demux->prev_image_buffer) == GST_BUFFER_SIZE(image_buffer))) {
+      if (!memcmp (GST_BUFFER_DATA(demux->prev_image_buffer), GST_BUFFER_DATA(image_buffer), GST_BUFFER_SIZE(image_buffer))) {
+        GST_INFO_OBJECT (demux, "current & previous embedded images are same..no need to post image again");
+        gst_buffer_unref (image_buffer);
+        goto skip_posting_image;
+      }
+    }
+
+    if (demux->prev_image_buffer) {
+      gst_buffer_unref (demux->prev_image_buffer);
+    }
+    demux->prev_image_buffer = gst_buffer_copy(image_buffer);
+
+    g_value_init (&codec_type, G_TYPE_STRING);
+    g_value_init (&image_data, GST_TYPE_BUFFER);
+    gst_value_set_buffer(&image_data, image_buffer);
+
+    image_header = g_strndup((gchar *) image_buffer->data, 8);
+
+    if((image_header[0] == 0xFF) && (image_header[1] == 0xD8)) {
+      GST_INFO_OBJECT(demux, "Found JPEG image header");
+      g_value_set_static_string (&codec_type, "image/jpeg");
+      gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
+    } else if (!g_strcmp0(image_header, "\211PNG\015\012\032\012")) {
+      GST_INFO_OBJECT(demux, "Found PNG image header");
+      g_value_set_static_string (&codec_type, "image/png");
+      gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
+    } else {
+      g_value_set_static_string (&codec_type, "image/unknown");
+      GST_INFO_OBJECT(demux, "Unknown image header");
+      gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
+    }
+
+    gst_tag_list_add_value (tag_list, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, &image_data);
+
+    GST_INFO_OBJECT(demux, "Set value : %s", g_value_get_string (&codec_type));
+    g_value_unset(&codec_type);
+
+    tag_message = gst_message_new_tag (GST_OBJECT_CAST (demux), tag_list);
+    if(!gst_element_post_message (GST_ELEMENT_CAST (demux), tag_message)) {
+      GST_ERROR_OBJECT (demux, "failed to post fixed image tag");
+    }
+
+    GST_INFO_OBJECT (demux, "successfully posted image tag...");
+    gst_buffer_unref (image_buffer);
+    g_free (image_header);
+  }
+
+skip_posting_image:
+
+  gst_hlsdemux2_destroy_fragment_download (demux);
+
+  if (demux->fdownloader->remaining_data) {
+    free (demux->fdownloader->remaining_data);
+    demux->fdownloader->remaining_data = NULL;
+  }
+
+  demux->fdownloader->remaining_size = 0;
+  demux->fdownloader->src_downloaded_size = 0;
+  demux->fdownloader->queue_downloaded_size = 0;
+  demux->fdownloader->download_stop_ts = demux->fdownloader->download_start_ts = 0;
+  demux->fdownloader->applied_fast_switch = FALSE;
+  demux->fdownloader->content_size = 0;
+
+  if (demux->cancelled || demux->flushing) {
+    GST_WARNING_OBJECT (demux, "returning false due to flushing/cancelled");
+    goto error;
+  } else if (demux->fdownloader->get_next_frag || demux->fdownloader->applied_fast_switch) {
+    GST_INFO_OBJECT (demux, "Requesting next fragment due to error or same sequence number from different variant");
+    goto exit;
+  }
+
+  demux->fdownloader->ndownloaded++;
+
+  GST_INFO_OBJECT (demux, "number of fragments downloaded = %d", demux->fdownloader->ndownloaded);
+
+  /* reset the count */
+  demux->soup_request_fail_cnt = HLSDEMUX2_SOUP_FAILED_CNT;
+
+exit:
+  if (demux->private_stream) {
+    g_free (demux->private_stream);
+    demux->private_stream = NULL;
+  }
+  g_mutex_unlock (demux->fdownloader->lock);
+
+  return TRUE;
+
+error:
+  if (demux->private_stream) {
+    g_free (demux->private_stream);
+    demux->private_stream = NULL;
+  }
+  g_mutex_unlock (demux->fdownloader->lock);
+
+  return FALSE;
+}
+
+static gboolean
+gst_hlsdemux2_change_playlist (GstHLSDemux2 * demux, guint max_bitrate, gboolean *is_switched)
+{
+  GList *previous_variant, *current_variant;
+  gint old_bandwidth, new_bandwidth;
+
+  previous_variant = demux->client->main->current_variant;
+  current_variant = gst_m3u8_client_get_playlist_for_bitrate (demux->client, max_bitrate);
+
+  old_bandwidth = GST_M3U8 (previous_variant->data)->bandwidth;
+  new_bandwidth = GST_M3U8 (current_variant->data)->bandwidth;
+
+  /* Don't do anything else if the playlist is the same */
+  if (new_bandwidth == old_bandwidth) {
+    if (is_switched)
+      *is_switched = FALSE;
+    return TRUE;
+  }
+
+  GST_M3U8_CLIENT_LOCK (demux->client);
+  demux->client->main->current_variant = current_variant;
+  GST_M3U8_CLIENT_UNLOCK (demux->client);
+
+  gst_m3u8_client_set_current (demux->client, current_variant->data);
+
+  GST_INFO_OBJECT (demux, "Client was on %dbps, max allowed is %dbps, switching"
+      " to bitrate %dbps", old_bandwidth, max_bitrate, new_bandwidth);
+
+  gst_hlsdemux2_apply_disc(demux);
+
+  if (is_switched)
+    *is_switched = TRUE;
+
+  return TRUE;
+}
+
+static gboolean
+gst_hlsdemux2_get_next_fragment (GstHLSDemux2 * demux, gboolean *is_error)
+{
+  const gchar *next_fragment_uri = NULL;;
+  gchar *next_fragment_key_uri = NULL;
+  gchar *iv = NULL;
+  GstClockTime duration;
+  GstClockTime timestamp;
+  gboolean discont = FALSE;
+  gboolean bret = TRUE;
+  GstClockTime lookup_time = 0;
+  guint i = 0;
+  GstHLSDemux2Stream *stream = NULL;
+
+  if (!demux->is_live) {
+    for (i = 0; i< HLSDEMUX2_STREAM_NUM; i++) {
+      stream = demux->streams[i];
+      if (stream) {
+        lookup_time = stream->lts + stream->frame_duration + (0.5 * GST_SECOND);
+        GST_INFO_OBJECT (stream->pad, "Lookup time = %"GST_TIME_FORMAT, GST_TIME_ARGS(lookup_time));
+        stream->frame_duration = 0;
+        if (stream->type == HLSDEMUX2_STREAM_AUDIO)
+          break;
+      }
+    }
+  }
+
+  if (!gst_m3u8_client_get_next_fragment (demux->client, lookup_time,
+    &discont, &next_fragment_uri, &duration, &timestamp, &next_fragment_key_uri, &iv)) {
+
+    GST_INFO_OBJECT (demux, "This playlist doesn't contain more fragments");
+
+    if (demux->is_live && (demux->client->update_failed_count < DEFAULT_FAILED_COUNT)) {
+      GST_WARNING_OBJECT (demux, "Could not get next fragment, try again after updating playlist...");
+      *is_error = FALSE;
+      return FALSE;
+    } else {
+      goto end_of_list;
+    }
+  }
+
+  demux->cfrag_dur = duration;
+  demux->fdownloader->cur_running_dur += duration;
+
+  GST_LOG_OBJECT (demux, "current running duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(demux->fdownloader->cur_running_dur));
+
+  GST_DEBUG_OBJECT (demux, "Fetching next fragment = %s & key uri = %s", next_fragment_uri, next_fragment_key_uri);
+
+  /* when hls requests next fragment due to some error like NOT_FOUND, then also we need to set apply disc */
+  if (discont || demux->fdownloader->get_next_frag)
+    gst_hlsdemux2_apply_disc (demux);
+
+  if (next_fragment_key_uri) {
+    /* download key data & initialize decryption with key data & IV */
+    GST_INFO_OBJECT (demux, "Fetching next fragment key %s", next_fragment_key_uri);
+
+    if (demux->kdownloader->prev_key_uri) {
+      if (strcmp (demux->kdownloader->prev_key_uri, next_fragment_key_uri)) {
+        /* if previous & current key uris are different, download new one */
+        if (demux->kdownloader->key) {
+          gst_buffer_unref (demux->kdownloader->key);
+          demux->kdownloader->key = NULL;
+        }
+
+        if (demux->kdownloader->prev_key_uri)
+          g_free (demux->kdownloader->prev_key_uri);
+
+        demux->kdownloader->prev_key_uri = g_strdup(next_fragment_key_uri);
+
+        /* download the key data as there is a change */
+        if (!gst_hlsdemux2_download_key (demux, next_fragment_key_uri)) {
+          GST_ERROR_OBJECT (demux, "failed to download key...");
+          goto error;
+        }
+      } else {
+        GST_INFO_OBJECT (demux, "already having the key...no need to download again");
+      }
+    } else {
+      if (demux->kdownloader->key) {
+        gst_buffer_unref (demux->kdownloader->key);
+        demux->kdownloader->key = NULL;
+      }
+
+      demux->kdownloader->prev_key_uri = g_strdup(next_fragment_key_uri);
+
+      if (!gst_hlsdemux2_download_key (demux, next_fragment_key_uri)) {
+        GST_ERROR_OBJECT (demux, "failed to download key...");
+        goto error;
+      }
+      /* reset the count */
+      demux->soup_request_fail_cnt = HLSDEMUX2_SOUP_FAILED_CNT;
+    }
+
+    if (!demux->kdownloader->key || !GST_BUFFER_DATA (demux->kdownloader->key)) {
+      GST_ERROR_OBJECT (demux, "eos received without key content...");
+      goto error;
+    }
+
+    if (!gst_m3u8_client_decrypt_init (demux->client, GST_BUFFER_DATA (demux->kdownloader->key), iv)) {
+      GST_ERROR_OBJECT (demux, "failed to initialize AES decryption...");
+      goto error;
+    }
+
+    demux->fdownloader->is_encrypted = TRUE;
+  }
+
+  if (!gst_hlsdemux2_download_fragment (demux, next_fragment_uri)) {
+    GST_ERROR_OBJECT (demux, "failed to download fragment...");
+    goto error;
+  }
+
+exit:
+  if (next_fragment_uri)
+    g_free ((gpointer)next_fragment_uri);
+  if (next_fragment_key_uri)
+    g_free ((gpointer)next_fragment_key_uri);
+  if (iv)
+    g_free ((gpointer)iv);
+
+  return bret;
+
+error:
+  if (!demux->flushing)
+    *is_error = TRUE;
+  bret = FALSE;
+  goto exit;
+
+ end_of_list:
+  GST_INFO_OBJECT (demux, "Reached end of playlist, sending EOS");
+
+  gst_hlsdemux2_push_eos (demux);
+
+  demux->end_of_playlist = TRUE;
+  bret = FALSE;
+  goto exit;
+}
+
+
+static gboolean
+gst_hlsdemux2_switch_playlist (GstHLSDemux2 * demux, gboolean *is_switched)
+{
+  GST_M3U8_CLIENT_LOCK (demux->client);
+  if (!demux->client->main->lists) {
+    /* not a variant to switch */
+    GST_M3U8_CLIENT_UNLOCK (demux->client);
+    GST_INFO_OBJECT (demux, "not a variant to switch...");
+    return TRUE;
+  }
+  GST_M3U8_CLIENT_UNLOCK (demux->client);
+
+  if (demux->force_lower_bitrate && (demux->fdownloader->ndownloaded % FORCE_LOW_BITRATE_AFTER_CNT == 0)) {
+    demux->fdownloader->download_rate = 0; // Using some temp lowest value
+    GST_WARNING_OBJECT (demux, "resetting to lowest one bitrate = %"G_GUINT64_FORMAT, demux->fdownloader->download_rate);
+  }
+
+  return gst_hlsdemux2_change_playlist (demux, demux->fdownloader->download_rate, is_switched);
+}
+
+static void
+gst_hlsdemux2_apply_disc (GstHLSDemux2 * demux)
+{
+  int i = 0;
+  GstHLSDemux2Stream *stream = NULL;
+
+  for (i = 0; i< HLSDEMUX2_STREAM_NUM; i++) {
+    stream = demux->streams[i];
+
+    if (stream) {
+      stream->apply_disc = TRUE;
+      GST_INFO_OBJECT (stream->pad, "apply discontinuity...");
+    }
+  }
+}
+
+static void
+gst_hlsdemux2_fragment_download_loop (GstHLSDemux2 * demux)
+{
+  gboolean is_error = FALSE;
+  gboolean bret = FALSE;
+  GTimeVal tmp_update = {0, };
+  GTimeVal current;
+  guint64 current_time = 0;
+  guint64 nextupdate_time = 0;
+
+  /* if variant playlist, get current subplaylist first */
+  if (gst_m3u8_client_has_variant_playlist(demux->client)) {
+    gboolean is_error = FALSE;
+
+    if (!gst_hlsdemux2_update_playlist (demux, FALSE, &is_error)) {
+      GST_ERROR_OBJECT (demux, "failed to update playlist. uri : %s", gst_m3u8_client_get_current_uri(demux->client));
+      GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND, ("Could not update the playlist"), (NULL));
+      goto exit;
+    }
+  } else if (demux->is_live) {
+    /* single variant live.. so schedule for starting */
+    if (demux->is_live)
+      gst_hlsdemux2_schedule (demux);
+  }
+
+  if (demux->fdownloader->find_mediaseq) {
+    GList *walk;
+    GstClockTime current_pos, target_pos;
+    gint current_sequence;
+    GstM3U8MediaFile *file;
+    guint i = 0;
+    GstHLSDemux2Stream *stream = NULL;
+
+    GST_M3U8_CLIENT_LOCK (demux->client);
+    file = GST_M3U8_MEDIA_FILE (demux->client->current->files->data);
+    current_sequence = file->sequence;
+    current_pos = 0 ;
+    target_pos = demux->fdownloader->seeked_pos;
+    for (walk = demux->client->current->files; walk; walk = walk->next) {
+      file = walk->data;
+
+      current_sequence = file->sequence;
+      if (current_pos <= target_pos &&
+        target_pos < current_pos + file->duration) {
+        break;
+      }
+      current_pos += file->duration;
+    }
+    GST_M3U8_CLIENT_UNLOCK (demux->client);
+
+    if (walk == NULL) {
+      GST_WARNING_OBJECT (demux, "Could not find seeked fragment");
+    }
+    GST_M3U8_CLIENT_LOCK (demux->client);
+    GST_INFO_OBJECT (demux, "seeking to sequence %d", current_sequence);
+    demux->client->sequence = current_sequence;
+    GST_M3U8_CLIENT_UNLOCK (demux->client);
+    demux->ns_start = demux->fdownloader->cur_running_dur = current_pos;  // NON-accurate seek
+
+    for (i = 0; i< HLSDEMUX2_STREAM_NUM; i++) {
+      stream = demux->streams[i];
+#ifdef LATEST_AV_SYNC
+      if (stream) {
+        stream->lts = stream->total_stream_time = current_pos;
+        GST_INFO_OBJECT (stream->pad, "Changed stream->lts to %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->lts));
+      }
+#else
+      if (stream && stream->type == HLSDEMUX2_STREAM_AUDIO) {
+        stream->lts  = current_pos;
+      }
+#endif
+    }
+
+    demux->fdownloader->find_mediaseq = FALSE;
+  }
+
+  demux->target_duration = gst_m3u8_client_get_target_duration(demux->client);
+  demux->total_cache_duration = DEFAULT_NUM_FRAGMENTS_CACHE * demux->target_duration;
+  demux->is_live = gst_m3u8_client_is_live(demux->client);
+
+  GST_INFO_OBJECT (demux, "Total cache duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(demux->total_cache_duration));
+
+  while (TRUE) {
+
+    if (demux->cancelled)
+      goto exit;
+
+    /* get the next fragement */
+    bret = gst_hlsdemux2_get_next_fragment (demux, &is_error);
+
+    if (!bret) {
+      if (is_error) {
+        GST_ERROR_OBJECT (demux, "error in getting next fragment");
+        GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("could not download fragment"), (NULL));
+        goto exit;
+      } else {
+        if (!demux->end_of_playlist) {
+          if (demux->flushing) {
+            GST_WARNING_OBJECT (demux, "SEEK is in progress.. pause the task");
+            goto exit;
+          } else if (demux->client->update_failed_count < DEFAULT_FAILED_COUNT) {
+            GST_WARNING_OBJECT (demux, "Could not update fragment & playlist update failed count = %d",
+              demux->client->update_failed_count);
+          } else {
+            GST_ERROR_OBJECT (demux, "Could not get next fragment..");
+            GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND, ("Could not get next fragment..."), (NULL));
+            goto exit;
+          }
+        } else {
+          GST_INFO_OBJECT (demux, "end of fragment download, doing pause");
+          goto exit;
+        }
+      }
+    } else {
+      /* reset the update failed count */
+      demux->client->update_failed_count = 0;
+    }
+
+    if (demux->cancelled)
+      goto exit;
+
+    if (demux->is_live) {
+      /* get the current time */
+      current.tv_sec = current.tv_usec = 0;
+      g_get_current_time (&current);
+
+      current_time = ((guint64)current.tv_sec * (guint64)1000000) + (guint64)current.tv_usec;
+      nextupdate_time = ((guint64)demux->next_update.tv_sec * (guint64)1000000) + (guint64)demux->next_update.tv_usec;
+    }
+
+    if (demux->is_live && ((current_time > nextupdate_time) || !bret)) {
+      gboolean is_switched = FALSE;
+
+      /* try to switch to another bitrate if needed */
+      // TODO: take care of return value
+      gst_hlsdemux2_switch_playlist (demux, &is_switched);
+
+      g_mutex_lock (demux->pl_update_lock);
+
+      /*  block until the next scheduled update or the exit signal */
+      bret = g_cond_timed_wait (demux->pl_update_cond, demux->pl_update_lock, &demux->next_update);
+
+      g_mutex_unlock (demux->pl_update_lock);
+
+      GST_DEBUG_OBJECT (demux, "playlist update wait is completed. reason : %s",  bret ? "Received signal" : "time-out");
+
+      tmp_update.tv_sec = 0;
+      tmp_update.tv_usec = 0;
+
+      g_get_current_time (&tmp_update);
+
+      if (bret) {
+        GST_DEBUG_OBJECT (demux, "Sombody signalled manifest waiting... going to exit and diff = %ld",
+            ((demux->next_update.tv_sec * 1000000)+ demux->next_update.tv_usec) - ((tmp_update.tv_sec * 1000000)+ tmp_update.tv_usec));
+        goto exit;
+      } else if (demux->cancelled) {
+        GST_WARNING_OBJECT (demux, "closing is in progress..exit now");
+        goto exit;
+      }
+
+      if (!gst_hlsdemux2_update_playlist (demux, FALSE, &is_error)) {
+        if (is_error) {
+          GST_ERROR_OBJECT (demux, "failed to update playlist...");
+          GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to update playlist"), (NULL));
+          goto exit;
+        } else {
+          if (demux->flushing) {
+            GST_WARNING_OBJECT (demux, "SEEK is in progress.. pause the task");
+            goto exit;
+          } else if (demux->client->update_failed_count < DEFAULT_FAILED_COUNT) {
+            GST_WARNING_OBJECT (demux, "Could not update playlist & playlist update failed count = %d",
+              demux->client->update_failed_count);
+            continue;
+          } else {
+            GST_ERROR_OBJECT (demux, "Could not update playlist..");
+            GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND, ("Could not update playlist..."), (NULL));
+            goto exit;
+          }
+        }
+      }
+
+    } else {
+      gboolean is_switched = FALSE;
+
+      /* try to switch to another bitrate if needed */
+      // TODO: take care of return value
+
+      /* when in recovery mode, do not obey download rates */
+      if (demux->pldownloader->recovery_mode == HLSDEMUX2_NO_RECOVERY)
+        gst_hlsdemux2_switch_playlist (demux, &is_switched);
+
+      if (is_switched) {
+        if (!gst_hlsdemux2_update_playlist (demux, FALSE, &is_error)) {
+          if (is_error) {
+            GST_ERROR_OBJECT (demux, "failed to update playlist...");
+            GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to update playlist"), (NULL));
+            goto exit;
+          } else {
+            if (demux->flushing) {
+              GST_WARNING_OBJECT (demux, "SEEK is in progress.. pause the task");
+              goto exit;
+            } else if (demux->client->update_failed_count < DEFAULT_FAILED_COUNT) {
+              GST_WARNING_OBJECT (demux, "Could not update playlist & playlist update failed count = %d",
+                demux->client->update_failed_count);
+              continue;
+            } else {
+              GST_ERROR_OBJECT (demux, "Could not update playlist..");
+              GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND, ("Could not update playlist..."), (NULL));
+              goto exit;
+            }
+          }
+        }
+      } else if (demux->is_live) {
+        GstClockTime current_time = gst_util_get_timestamp();
+
+        if ((current_time - demux->pldownloader->download_start_ts) <
+          (PLAYLIST_REFRESH_TIMEOUT - (HLSDEMUX2_FAST_CHECK_CRITICAL_TIME_FACTOR * demux->target_duration) - HLSDEMUX2_OVERHEAD)) {
+          GST_INFO_OBJECT (demux, "Eligible to download next fragment w/o playlist update : "
+            "elapsed time since last playlist request = %"GST_TIME_FORMAT" and max_time_limit = %"GST_TIME_FORMAT,
+            GST_TIME_ARGS(current_time - demux->pldownloader->download_start_ts),
+            GST_TIME_ARGS(PLAYLIST_REFRESH_TIMEOUT - (HLSDEMUX2_FAST_CHECK_CRITICAL_TIME_FACTOR * demux->target_duration) - HLSDEMUX2_OVERHEAD));
+        } else {
+
+          GST_INFO_OBJECT (demux, "NOT Eligible to download next fragment w/o playlist update : "
+            "elapsed time since previous request = %"GST_TIME_FORMAT" and max_time_limit = %"GST_TIME_FORMAT,
+            GST_TIME_ARGS(current_time - demux->pldownloader->download_start_ts),
+            GST_TIME_ARGS(PLAYLIST_REFRESH_TIMEOUT - (HLSDEMUX2_FAST_CHECK_CRITICAL_TIME_FACTOR * demux->target_duration) - HLSDEMUX2_OVERHEAD));
+
+          /* we are not eligible to download, next fragment.. So wait till next playlist update */
+          g_mutex_lock (demux->pl_update_lock);
+          /*  block until the next scheduled update or the exit signal */
+          bret = g_cond_timed_wait (demux->pl_update_cond, demux->pl_update_lock, &demux->next_update);
+          g_mutex_unlock (demux->pl_update_lock);
+
+          GST_DEBUG_OBJECT (demux, "playlist update wait is completed. reason : %s",  bret ? "Received signal" : "time-out");
+
+          tmp_update.tv_sec = 0;
+          tmp_update.tv_usec = 0;
+
+          g_get_current_time (&tmp_update);
+
+          if (bret) {
+            GST_DEBUG_OBJECT (demux, "Sombody signalled manifest waiting... going to exit and diff = %ld",
+                ((demux->next_update.tv_sec * 1000000)+ demux->next_update.tv_usec) - ((tmp_update.tv_sec * 1000000)+ tmp_update.tv_usec));
+            goto exit;
+          } else if (demux->cancelled) {
+            GST_WARNING_OBJECT (demux, "closing is in progress..exit now");
+            goto exit;
+          }
+
+          if (!gst_hlsdemux2_update_playlist (demux, FALSE, &is_error)) {
+            if (is_error) {
+              GST_ERROR_OBJECT (demux, "failed to update playlist...");
+              GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to update playlist"), (NULL));
+              goto exit;
+            } else {
+              if (demux->flushing) {
+                GST_WARNING_OBJECT (demux, "SEEK is in progress.. pause the task");
+                goto exit;
+              } else if (demux->client->update_failed_count < DEFAULT_FAILED_COUNT) {
+                GST_WARNING_OBJECT (demux, "Could not update playlist & playlist update failed count = %d",
+                  demux->client->update_failed_count);
+                continue;
+              } else {
+                GST_ERROR_OBJECT (demux, "Could not update playlist..");
+                GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND, ("Could not update playlist..."), (NULL));
+                goto exit;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+exit:
+  GST_WARNING_OBJECT (demux, "Going to PAUSE download task from self");
+  gst_task_pause (demux->download_task);
+  return;
+}
+
+static void
+gst_hlsdemux2_calculate_popped_duration (GstHLSDemux2 *demux, GstHLSDemux2Stream *stream,
+    GstBuffer *outbuf)
+{
+  gpointer data = NULL;
+  gint i = g_queue_get_length (stream->queue);
+
+  /* get the buffer with valid timestamp from tail of the queue */
+  while (i > 1) {
+    data = g_queue_peek_nth (stream->queue, (i - 1));
+    if (data == NULL) {
+      return;
+    }
+
+    if (GST_IS_BUFFER ((GstBuffer *)data)) {
+      if (GST_BUFFER_TIMESTAMP_IS_VALID(data)) {
+        /* found valid timestamp & stop searching */
+        GST_LOG_OBJECT (stream->pad, "data found buffer with valid ts = %"GST_TIME_FORMAT " len = %d & i = %d",
+          GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(data)), g_queue_get_length (stream->queue), i);
+        break;
+      }
+    }
+    i--;
+  }
+
+  if (data == NULL) {
+    return;
+  }
+
+  if (GST_BUFFER_TIMESTAMP (outbuf) <= GST_BUFFER_TIMESTAMP ((GstBuffer *)data)) {
+    stream->cached_duration = GST_BUFFER_TIMESTAMP ((GstBuffer *)data) - GST_BUFFER_TIMESTAMP (outbuf);
+    GST_DEBUG_OBJECT (stream->pad, "cache duration in popping : %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->cached_duration));
+  } else {
+    GST_ERROR_OBJECT (stream->pad, "Wrong order.. not calculating");
+  }
+
+  return;
+}
+
+static void
+gst_hlsdemux2_push_loop (GstHLSDemux2Stream *stream)
+{
+  GstHLSDemux2 *demux = stream->parent;
+  GstFlowReturn fret = GST_FLOW_OK;
+  gpointer data = NULL;
+
+  // TODO: need to take care of EOS handling....
+
+  if (demux->cancelled || demux->flushing)
+    goto error;
+
+  g_mutex_lock (stream->queue_lock);
+
+  if (g_queue_is_empty (stream->queue)) {
+    GST_LOG_OBJECT (stream->pad,"queue is empty wait till, some buffers are available...");
+    g_cond_wait (stream->queue_empty, stream->queue_lock);
+    GST_LOG_OBJECT (stream->pad,"Received queue empty signal...");
+  }
+
+  if (demux->cancelled || demux->flushing) {
+    GST_ERROR_OBJECT (stream->pad, "Shutting down push loop");
+    g_mutex_unlock (stream->queue_lock);
+    goto error;
+  }
+
+  if (g_queue_is_empty (stream->queue)) {
+    GST_ERROR_OBJECT (stream->pad, "Queue empty undesired....");
+    g_mutex_unlock (stream->queue_lock);
+    goto error;
+  }
+
+  data = g_queue_pop_head (stream->queue);
+  if (!data) {
+    GST_ERROR_OBJECT (stream->pad, "Received null data...");
+    GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Unhandled GstObjectType"), (NULL));
+    g_mutex_unlock (stream->queue_lock);
+    goto error;
+  }
+
+  /*  Calculate duration only when
+    *  1. popped obj is a buffer and
+    *  2. buffer has valid ts and
+    *  3. queue length > 1
+   */
+
+  if (GST_IS_BUFFER(data) &&
+     GST_BUFFER_TIMESTAMP_IS_VALID(data) ) {
+
+    /* calculate buffering duration */
+    gst_hlsdemux2_calculate_popped_duration (demux, stream, data);
+
+    if (stream->cached_duration < 0) {
+      GST_WARNING_OBJECT (stream->pad, "Wrong cached duration in push_loop...\n");
+      stream->cached_duration = 0;
+    }
+  }
+
+  g_mutex_unlock (stream->queue_lock);
+
+  if (GST_IS_EVENT(data)) {
+    GstEvent *event = (GstEvent *)data;
+
+    switch (GST_EVENT_TYPE (event)) {
+      case GST_EVENT_NEWSEGMENT: {
+        GstFormat format;
+        gboolean update;
+        gdouble rate, arate;
+        gint64 start, stop, pos;
+        gst_event_parse_new_segment_full(event, &update, &rate, &arate, &format, &start, &stop, &pos);
+        GST_INFO_OBJECT (stream->pad, "Pushing newsegment to downstream : rate = %0.3f, start = %"GST_TIME_FORMAT
+          ", stop = %"GST_TIME_FORMAT, rate, GST_TIME_ARGS(start), GST_TIME_ARGS(stop));
+      }
+      break;
+      case GST_EVENT_EOS:
+      GST_INFO_OBJECT (stream->pad, "going to push eos event to downstream");
+      stream->eos = TRUE;
+      break;
+      default:
+      GST_ERROR_OBJECT (stream->pad, "not handled event...still pushing event");
+      break;
+    }
+    if (!gst_pad_push_event (stream->pad, event)) {
+      GST_ERROR_OBJECT (demux, "failed to push newsegment event");
+      GST_ELEMENT_ERROR (demux, CORE, PAD, ("failed to push '%s' event", GST_EVENT_TYPE_NAME(event)), (NULL));
+      goto error;
+    }
+
+    GST_INFO_OBJECT (stream->pad, "Pushed '%s' event...", GST_EVENT_TYPE_NAME(event));
+
+    if (stream->eos) {
+      //gst_element_post_message (GST_ELEMENT_CAST (stream->sink), gst_message_new_eos (GST_OBJECT_CAST(stream->sink)));
+      GST_INFO_OBJECT (stream->pad, "Pausing the task");
+      goto error;
+    }
+  } else if (GST_IS_BUFFER(data)) {
+    GstCaps *temp_caps = NULL;
+    g_cond_signal (stream->queue_full);
+
+    GST_DEBUG_OBJECT (stream->pad, "Pushing buffer : size = %d, ts = %"GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT,
+      GST_BUFFER_SIZE(data), GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(data)), GST_TIME_ARGS(GST_BUFFER_DURATION(data)));
+
+    temp_caps = gst_buffer_get_caps((GstBuffer *)data);
+    temp_caps = gst_caps_make_writable (temp_caps);
+    gst_caps_set_simple (temp_caps,"hls_streaming", G_TYPE_BOOLEAN, TRUE, NULL);
+    gst_buffer_set_caps((GstBuffer *)data, temp_caps);
+    gst_caps_unref(temp_caps);
+
+    /* push data to downstream*/
+    fret = gst_pad_push (stream->pad, data);
+    if (fret != GST_FLOW_OK) {
+      GST_ERROR_OBJECT (stream->pad, "failed to push data, reason : %s", gst_flow_get_name (fret));
+      goto error;
+    }
+  } else {
+    GST_ERROR_OBJECT (stream->pad, "unhandled object type..still pushing");
+    //GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Unhandled GstObjectType"), (NULL));
+    //return;
+    gst_object_unref (data);
+  }
+
+  if (demux->cancelled || demux->flushing) {
+    goto error;
+  }
+
+  return;
+
+error:
+  {
+    GST_WARNING_OBJECT (stream->pad, "Pausing the push task...");
+
+    if (fret < GST_FLOW_UNEXPECTED) {
+      GST_ERROR_OBJECT (stream->pad, "Crtical error in push loop....");
+      GST_ELEMENT_ERROR (demux, CORE, PAD, ("failed to push. reason - %s", gst_flow_get_name (fret)), (NULL));
+    }
+
+    gst_pad_pause_task (stream->pad);
+    return;
+  }
+}
+
+// TODO: need to review change_playlist API
+
+static gboolean
+gst_hlsdemux2_schedule (GstHLSDemux2 * demux)
+{
+  gfloat update_factor;
+  gint count;
+  GstClockTime last_frag_duration;
+
+  /* As defined in Â§6.3.4. Reloading the Playlist file:
+   * "If the client reloads a Playlist file and finds that it has not
+   * changed then it MUST wait for a period of time before retrying.  The
+   * minimum delay is a multiple of the target duration.  This multiple is
+   * 0.5 for the first attempt, 1.5 for the second, and 3.0 thereafter."
+   */
+  count = demux->client->update_failed_count;
+  if (count < 3)
+    update_factor = update_interval_factor[count];
+  else
+    update_factor = update_interval_factor[3];
+
+  /* schedule the next update using the target duration field of the
+   * playlist */
+  demux->next_update.tv_sec = 0;
+  demux->next_update.tv_usec = 0;
+
+  last_frag_duration = gst_m3u8_client_get_last_fragment_duration (demux->client);
+
+  GST_DEBUG_OBJECT (demux, "last fragment duration = %"GST_TIME_FORMAT" and next update = %"GST_TIME_FORMAT,
+    GST_TIME_ARGS(last_frag_duration), GST_TIME_ARGS(GST_TIME_AS_USECONDS(last_frag_duration) * 1000));
+
+  g_get_current_time (&demux->next_update);
+
+  //g_time_val_add (&demux->next_update, last_frag_duration / GST_SECOND * G_USEC_PER_SEC * update_factor);
+  g_time_val_add (&demux->next_update, GST_TIME_AS_USECONDS(last_frag_duration)* update_factor);
+
+  return TRUE;
+}
+
+static void
+gst_hlsdemux2_new_pad_added (GstElement *element, GstPad *srcpad, gpointer data)
+{
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
+  GstPad *sinkpad = NULL;
+  GstCaps *caps = NULL;
+  HLSDemux2SinkBin *sinkbin = NULL;
+  gchar *demuxer_name = NULL;
+  gchar *src_pad_name = NULL;
+
+  GST_INFO_OBJECT (demux, "received the src_pad '%s' from mpeg2ts demuxer...", GST_PAD_NAME(srcpad));
+
+  if (strstr (GST_PAD_NAME(srcpad), "private")) {
+    /* handle private image TAG */
+    gst_hlsdemux2_handle_private_pad (demux, srcpad);
+    return;
+  }
+
+  caps = GST_PAD_CAPS (srcpad);
+  demuxer_name = GST_ELEMENT_NAME (element);
+
+  sinkbin = gst_hlsdemux2_create_stream (demux, demuxer_name, caps);
+  if (!sinkbin) {
+    return;
+  }
+
+  sinkpad = gst_element_get_pad(GST_ELEMENT(sinkbin->sinkbin), "sink");
+  if (!sinkpad) {
+    GST_ERROR_OBJECT (demux, "failed to get sinkpad from element  - %s", GST_PAD_NAME(sinkbin->sinkbin));
+    GST_ELEMENT_ERROR (demux, CORE, PAD, ("could not get sink pad"), (NULL));
+    return;
+  }
+
+  /* link demuxer srcpad & sink element's sink pad */
+  if (gst_pad_link(srcpad, sinkpad) != GST_PAD_LINK_OK) {
+    GST_ERROR_OBJECT (demux, "failed to link pad '%s' &  sink's sink pad", GST_PAD_NAME(srcpad));
+    GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("Could not link pads.."), (NULL));
+    gst_object_unref(sinkpad);
+    return;
+  }
+
+  if (sinkbin->parser) {
+    GST_INFO_OBJECT (demux, "linking parser");
+    if (!gst_element_link_many (sinkbin->queue, sinkbin->parser, sinkbin->sink, NULL)) {
+      GST_ERROR_OBJECT (demux, "failed to link sink bin elements");
+    GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("Could not link pads.."), (NULL));
+      gst_object_unref(sinkpad);
+      return;
+    }
+  } else {
+    if (!gst_element_link_many (sinkbin->queue, sinkbin->sink, NULL)) {
+      GST_ERROR_OBJECT (demux, "failed to link sink bin elements");
+      GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("Could not link pads.."), (NULL));
+      gst_object_unref(sinkpad);
+      return;
+    }
+  }
+  demux->fdownloader->cur_stream_cnt++;
+
+  src_pad_name = gst_pad_get_name(srcpad);
+  GST_INFO_OBJECT (demux, "succesfully linked pad (%s) with stream pad and current stream cnt = %d",
+    src_pad_name, demux->fdownloader->cur_stream_cnt);
+  g_free(src_pad_name);
+  src_pad_name = NULL;
+
+  gst_element_set_state (GST_ELEMENT(sinkbin->sinkbin), GST_STATE_PLAYING);
+
+  gst_object_unref (sinkpad);
+}
+
+static gboolean
+gst_hlsdemux2_check_stream_type_exist (GstHLSDemux2 *demux, HLSDEMUX2_STREAM_TYPE stream_type)
+{
+  int i = 0;
+  GstHLSDemux2Stream *stream = NULL;
+
+  for (i = 0; i< HLSDEMUX2_STREAM_NUM; i++) {
+    stream = demux->streams[i];
+
+    if (stream && (stream->type == stream_type)) {
+      GST_INFO_OBJECT (demux, "stream type '%d' is already present", stream_type);
+      return TRUE;
+    }
+  }
+
+  GST_INFO_OBJECT (demux, "received new stream type [%d]", stream_type);
+
+  return FALSE;
+}
+
+static HLSDemux2SinkBin *
+gst_hlsdemux2_create_stream (GstHLSDemux2 *demux, gchar *demuxer_name, GstCaps *caps)
+{
+  GstHLSDemux2Stream *stream = NULL;
+  GstPad *sinkpad = NULL;
+  GstPad *linkpad = NULL;
+  HLSDEMUX2_STREAM_TYPE stream_type;
+  gchar *element_name = NULL;
+  gboolean stream_exist = FALSE;
+  gulong sink_probe;
+  HLSDemux2SinkBin *bin = NULL;
+  GstStructure *structure = NULL;
+  gchar *mime = NULL;
+  gchar *stream_name = NULL;
+
+  stream = g_new0 (GstHLSDemux2Stream, 1);
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  mime = gst_structure_get_name (structure);
+
+  if (strstr (mime, "video")) {
+    stream_type = HLSDEMUX2_STREAM_VIDEO;
+    GST_DEBUG_OBJECT (demux, "Its a Multi-variant, Audio only stream..");
+    demux->stream_config = HLSDEMUX2_MULTI_VARIANT;
+    stream_name = g_strdup ("video");
+  } else if (strstr (mime, "audio")) {
+    stream_type = HLSDEMUX2_STREAM_AUDIO;
+    stream_name = g_strdup ("audio");
+  } else if (strstr (mime, "subpicture")) {
+    stream_type = HLSDEMUX2_STREAM_TEXT;
+    stream_name = g_strdup ("subpicture");
+  } else if (strstr (mime, "private")) {
+    stream_type = HLSDEMUX2_STREAM_PRIVATE;
+    stream_name = g_strdup ("private");
+  } else {
+    GST_ELEMENT_ERROR (demux, CORE, PAD, ("Received unknown named pad"), (NULL));
+    goto error;
+  }
+
+  stream_exist = gst_hlsdemux2_check_stream_type_exist (demux, stream_type);
+
+  if (!stream_exist) {
+    stream = g_new0 (GstHLSDemux2Stream, 1);
+    gst_hlsdemux2_stream_init (demux, stream, stream_type, stream_name, caps);
+
+    if (!stream->is_linked) {
+      goto error;
+    }
+  } else {
+    int i = 0;
+
+    for (i = 0; i< HLSDEMUX2_STREAM_NUM; i++) {
+      stream = demux->streams[i];
+      if (stream && (stream->type == stream_type)) {
+        GST_INFO_OBJECT (demux, "found the stream - '%d'", stream->type);
+        break;
+      }
+    }
+  }
+
+  if (!stream)
+    goto error;
+
+  bin = g_new0 (HLSDemux2SinkBin, 1);
+
+  element_name = g_strdup_printf("%s-%s", stream_name, "bin");
+  bin->sinkbin = GST_BIN(gst_bin_new (element_name));
+  if (!bin->sinkbin) {
+    GST_ERROR_OBJECT (demux, "failed to create sink bin - %s", element_name);
+    GST_ELEMENT_ERROR (demux, CORE, FAILED, ("failed to create bin - %s", element_name), (NULL));
+    goto error;
+  }
+  g_free (element_name);
+  element_name = NULL;
+
+  /* create queue element */
+  element_name = g_strdup_printf("%s-%s", stream_name, "queue");
+  bin->queue =  gst_element_factory_make ("queue", element_name);
+  if (!bin->queue) {
+    GST_ERROR_OBJECT (demux, "failed to create queue element - %s", element_name);
+    GST_ELEMENT_ERROR (demux, CORE, FAILED, ("failed to create element - %s", element_name), (NULL));
+    goto error;
+  }
+  g_free (element_name);
+  element_name = NULL;
+
+  if ((stream->type == HLSDEMUX2_STREAM_AUDIO) &&
+    g_strstr_len(demuxer_name, strlen(demuxer_name), "id3")) {
+    /* create parser element */
+
+    GST_INFO_OBJECT (stream->pad, "demuxer is id3demuxer, so create audio parser...");
+
+    element_name = g_strdup_printf("%s-%s", stream_name, "parse");
+    bin->parser =  gst_element_factory_make ("aacparse", element_name);
+    if (!bin->parser) {
+      GST_ERROR_OBJECT (demux, "failed to create parser element - %s", element_name);
+      GST_ELEMENT_ERROR (demux, CORE, FAILED, ("failed to create element - %s", element_name), (NULL));
+      goto error;
+    }
+    g_free (element_name);
+    element_name = NULL;
+    gst_bin_add (GST_BIN (bin->sinkbin), bin->parser);
+  }
+
+  /* create sink element */
+  element_name = g_strdup_printf("%s-%s", stream_name, "sink");
+  bin->sink =  gst_element_factory_make ("appsink", element_name);
+  if (!bin->sink) {
+    GST_ERROR_OBJECT (demux, "failed to create sink element - %s", element_name);
+    GST_ELEMENT_ERROR (demux, CORE, FAILED, ("failed to create element - %s", element_name), (NULL));
+    goto error;
+  }
+
+  g_object_set (G_OBJECT (bin->sink), "sync", FALSE, "emit-signals", TRUE, NULL);
+  g_signal_connect (bin->sink, "new-buffer",  G_CALLBACK (gst_hlsdemux2_downloader_new_buffer), stream);
+  g_signal_connect (bin->sink, "eos",  G_CALLBACK (gst_hlsdemux2_downloader_eos), stream);
+
+  gst_bin_add_many (GST_BIN (bin->sinkbin), bin->queue, bin->sink, NULL);
+
+  gst_bin_add (GST_BIN (demux->fdownloader->pipe), GST_ELEMENT(bin->sinkbin));
+
+  /* set queue element to PLAYING state */
+  gst_element_set_state (GST_ELEMENT(bin->sinkbin), GST_STATE_READY);
+
+  sinkpad = gst_element_get_pad(bin->sink, "sink");
+  if (!sinkpad) {
+    GST_ERROR_OBJECT (demux, "failed to get sinkpad from element  - %s", element_name);
+    GST_ELEMENT_ERROR (demux, CORE, PAD, ("Count not get sink pad"), (NULL));
+    goto error;
+  }
+  g_free (element_name);
+  element_name = NULL;
+
+  /* adding probe to get new segment events */
+  sink_probe = gst_pad_add_event_probe (sinkpad,
+      G_CALLBACK (gst_hlsdemux2_sink_event_handler), stream);
+
+  if (!stream_exist) {
+    /* add stream to stream_type list */
+    demux->streams[stream_type] = stream;
+    demux->active_stream_cnt++;
+    GST_INFO_OBJECT (demux, "number of active streams = %d", demux->active_stream_cnt);
+  }
+
+  linkpad = gst_element_get_pad(bin->queue, "sink");
+  if (!linkpad) {
+    element_name = gst_element_get_name (bin->queue);
+    GST_ERROR_OBJECT (demux, "failed to get sinkpad from element  - %s", element_name);
+    GST_ELEMENT_ERROR (demux, CORE, PAD, ("could not get sink pad"), (NULL));
+    goto error;
+  }
+
+  gst_pad_set_active(linkpad,TRUE);
+
+  gst_element_add_pad (GST_ELEMENT(bin->sinkbin), gst_ghost_pad_new ("sink", linkpad));
+
+  GST_INFO_OBJECT (stream->pad, "successfully created stream...");
+
+  demux->fdownloader->sinkbins = g_list_append (demux->fdownloader->sinkbins, bin);
+
+  g_cond_signal (demux->post_msg_start);
+
+  g_free (stream_name);
+
+  return bin;
+
+error:
+  g_free (stream);
+  if (element_name)
+    g_free (element_name);
+
+  if (stream_name)
+    g_free (stream_name);
+
+  return NULL;
+}
+
+static gboolean
+gst_hlsdemux2_private_image_to_vid(gpointer user_data,GstBuffer *image_buffer)
+{
+  GstHLSDemux2PvtStream *pvt_stream = (GstHLSDemux2PvtStream *) user_data;
+  GstHLSDemux2 *demux = (GstHLSDemux2 *) pvt_stream->parent;
+  GstPad *pad, *srcpad;
+  GstElement *appsrc, *appsink, *dec, *videorate, *capsfilter, *enc;
+  GstCaps *scale_caps, *image_caps;
+  GstBus * bus;
+  GstFlowReturn fret = GST_FLOW_OK;
+
+  gchar *image_header = g_strndup((gchar *) image_buffer->data, 8);
+  if(!((image_header[0] == 0xFF) && (image_header[1] == 0xD8))) {
+    GST_WARNING_OBJECT(demux, "Not a valid JPEG image header : %d %d",image_header[0],image_header[1]);
+    goto error;
+  }
+
+  GST_DEBUG_OBJECT(demux, "IMAGE DATA [%d,%d]",pvt_stream->image_buffer->data[0],pvt_stream->image_buffer->data[1]);
+
+  GST_INFO_OBJECT (demux, "Creating jpeg->h264 conversion pipeline");
+
+  pvt_stream->convert_pipe = gst_pipeline_new ("jpegdec-pipe");
+  if (!pvt_stream->convert_pipe) {
+    GST_ERROR_OBJECT (demux, "failed to create pipeline");
+    goto error;
+  }
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pvt_stream->convert_pipe));
+  gst_bus_add_watch (bus, (GstBusFunc)gst_hlsdemux2_imagebuf_pipe_bus_cb, user_data);
+  gst_object_unref (bus);
+
+  appsrc = gst_element_factory_make ("appsrc", "imgbuf-src");
+  if (!appsrc) {
+    GST_ERROR_OBJECT (demux, "failed to create appSrc element");
+    goto error;
+  }
+
+  appsink = gst_element_factory_make ("appsink", "imgbuf-sink");
+  if (!appsink) {
+    GST_ERROR_OBJECT (demux, "failed to create appSink element");
+    goto error;
+  }
+
+  dec = gst_element_factory_make ("jpegdec", "jpeg-decoder");
+  if (!dec) {
+    GST_ERROR_OBJECT (demux, "failed to create jpeg-decoder element");
+    goto error;
+  }
+
+  videorate = gst_element_factory_make ("videorate", "video-rate");
+  if (!videorate) {
+    GST_ERROR_OBJECT (demux, "failed to create ffmpeg-converter element");
+    goto error;
+  }
+
+  capsfilter = gst_element_factory_make ("capsfilter", "caps-filter");
+  if (!capsfilter) {
+    GST_ERROR_OBJECT (demux, "failed to create caps-filter element");
+    goto error;
+  }
+
+  scale_caps = gst_caps_new_simple ("video/x-raw-yuv",
+      "width" , G_TYPE_INT, 480,
+      "height", G_TYPE_INT, 270,
+      "framerate",GST_TYPE_FRACTION,30,1,
+      "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('I','4','2','0'),
+      NULL);
+  g_object_set (capsfilter, "caps", scale_caps, NULL);
+
+  enc = gst_element_factory_make ("savsenc_h264", "h264-encoder");
+  if (!enc) {
+    GST_ERROR_OBJECT (demux, "failed to create h264-encoder element");
+    goto error;
+  }
+
+  image_caps = gst_caps_new_simple ("image/jpeg",
+      "framerate", GST_TYPE_FRACTION, 30, 1,
+      "width", G_TYPE_INT, 480,
+      "height", G_TYPE_INT, 270,
+      NULL);
+  gst_buffer_set_caps (image_buffer, image_caps);
+
+  gst_bin_add_many (GST_BIN (pvt_stream->convert_pipe), appsrc, dec, videorate, capsfilter, enc, appsink, NULL);
+  if (!gst_element_link_many ( appsrc, dec, videorate, capsfilter, enc, appsink, NULL)) {
+    GST_ERROR_OBJECT (demux, "failed to link elements...");
+    goto error;
+  }
+
+  pad = gst_element_get_static_pad(appsink,"sink");
+  gst_pad_add_buffer_probe (pad,G_CALLBACK (gst_hlsdemux2_set_video_buffer), user_data);
+  gst_pad_add_event_probe  (pad,G_CALLBACK (gst_hlsdemux2_done_video_buffer), user_data);
+  gst_element_set_state (pvt_stream->convert_pipe, GST_STATE_PLAYING);
+
+  fret = gst_app_src_push_buffer ((GstAppSrc *)appsrc, pvt_stream->image_buffer);
+  if(fret != GST_FLOW_OK){
+    GST_ERROR_OBJECT (demux, "Push Failed; Error: %s[%d]", gst_flow_get_name(fret),fret);
+    goto error;
+  }
+
+  fret = gst_app_src_end_of_stream ((GstAppSrc *)appsrc);
+  if(fret != GST_FLOW_OK){
+    GST_ERROR_OBJECT (demux, "Push EOS Failed; Error: %s[%d]", gst_flow_get_name(fret),fret);
+    goto error;
+  }
+  g_free(image_header);
+  image_header = NULL;
+  return TRUE;
+
+  error:
+    GST_ERROR_OBJECT (demux, "ERROR ERROR ERROR: tut tut tut ");
+    g_free(image_header);
+    image_header = NULL;
+    return FALSE;
+}
+
+static gboolean
+gst_hlsdemux2_push_dummy_data (GstHLSDemux2Stream *stream)
+{
+  GstHLSDemux2 *demux = stream->parent;
+  struct stat stat_results;
+  GstBuffer *buf = NULL;
+  gint iread = 0;
+  gint64 percent = 0;
+  GstCaps *caps = NULL;
+  GstBuffer *pushbuf = NULL;
+  GstClockTime stop = GST_CLOCK_TIME_NONE;
+  GstClockTime next_ts = GST_CLOCK_TIME_NONE;
+  gboolean first_frame = TRUE;
+  gint n = 0;
+  gboolean convert_success = TRUE;
+  GstHLSDemux2Stream *cur_stream = NULL;
+  int dummy_fp = -1;
+  GstClockTime cdisc = 0;
+
+  GST_INFO_OBJECT (demux, "START dummy video data thread");
+
+  /* Read dummy frame */
+  if(demux->has_image_buffer) {
+    GstHLSDemux2PvtStream *pvt_stream = demux->private_stream;
+
+    g_mutex_lock (pvt_stream->img_load_lock);
+    if(pvt_stream->got_img_buffer == FALSE)
+      g_cond_wait(pvt_stream->img_load_cond, pvt_stream->img_load_lock);
+    g_mutex_unlock (pvt_stream->img_load_lock);
+
+    GST_LOG_OBJECT (demux, "prev_image_buffer = %p and image_buffer = %p",
+      demux->prev_image_buffer, pvt_stream->image_buffer);
+
+    /* check whether it is same as previous image */
+    if (demux->prev_video_buffer && demux->prev_image_buffer &&
+      (GST_BUFFER_SIZE(demux->prev_image_buffer) == GST_BUFFER_SIZE(pvt_stream->image_buffer))) {
+      if (!memcmp (GST_BUFFER_DATA(demux->prev_image_buffer), GST_BUFFER_DATA(pvt_stream->image_buffer),
+          GST_BUFFER_SIZE(pvt_stream->image_buffer))) {
+        GST_INFO_OBJECT (demux, "current & previous embedded images are same..no need to prepare video buffer");
+        gst_buffer_unref(pvt_stream->image_buffer);
+        pvt_stream->image_buffer = NULL;
+        buf = gst_buffer_copy(demux->prev_video_buffer);
+        goto start_push;
+      }
+    }
+
+    if (demux->prev_image_buffer) {
+      gst_buffer_unref (demux->prev_image_buffer);
+    }
+    demux->prev_image_buffer = gst_buffer_copy(pvt_stream->image_buffer);
+
+    g_mutex_lock (pvt_stream->convert_lock);
+    convert_success = gst_hlsdemux2_private_image_to_vid(pvt_stream, pvt_stream->image_buffer);
+    if(convert_success)
+      g_cond_wait(pvt_stream->convert_cond, pvt_stream->convert_lock);
+    g_mutex_unlock (pvt_stream->convert_lock);
+
+    if(pvt_stream->convert_pipe){
+      pvt_stream->convert_pipe = NULL;
+      gst_object_unref(pvt_stream->convert_pipe);
+    }
+
+    if (demux->prev_video_buffer) {
+      gst_buffer_unref (demux->prev_video_buffer);
+      demux->prev_video_buffer = NULL;
+    }
+
+    if(convert_success){
+      buf = pvt_stream->video_buffer;
+      pvt_stream->video_buffer = NULL;
+      demux->prev_video_buffer = gst_buffer_copy(buf);
+      GST_DEBUG_OBJECT (demux, "Set Image from buffer - success  [%d,%d]", buf->data[0], buf->data[1]);
+      GST_INFO_OBJECT (demux, "Going to show embedded image");
+    }
+  }
+
+  //load black frame if error occured while creating video buffer.
+  if(demux->has_image_buffer == FALSE || convert_success == FALSE)
+  {
+    GST_INFO_OBJECT (demux, "Going to show fixed image");
+    dummy_fp = open (PREDEFINED_VIDEO_FRAME_LOCATION, O_RDONLY);
+    if (dummy_fp < 0) {
+      GST_ERROR_OBJECT (stream->pad, "failed to open dummy data file : %s...", PREDEFINED_VIDEO_FRAME_LOCATION);
+      GST_ELEMENT_ERROR (demux, RESOURCE, OPEN_READ, ("Failed open file '%s' for reading. reason : %s",PREDEFINED_VIDEO_FRAME_LOCATION ,g_strerror(errno)), (NULL));
+      goto quit;
+    }
+
+    GST_LOG_OBJECT (stream->pad, "opened dummy video file %s succefully...", PREDEFINED_VIDEO_FRAME_LOCATION);
+
+    if (fstat (dummy_fp, &stat_results) < 0) {
+      GST_ERROR_OBJECT (stream->pad, "failed to get stats of a file...");
+      GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("Failed get stats. reason : %s", g_strerror(errno)), (NULL));
+      close (dummy_fp);
+      goto quit;
+    }
+
+    GST_LOG_OBJECT (stream->pad, "size of the dummy file = %d\n", stat_results.st_size);
+
+    buf = gst_buffer_new_and_alloc (stat_results.st_size);
+    if (!buf) {
+      GST_ERROR_OBJECT (stream->pad, "failed to allocate memory...");
+      GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
+      close (dummy_fp);
+      goto quit;
+    }
+
+    iread = read (dummy_fp, GST_BUFFER_DATA (buf), stat_results.st_size);
+
+    close (dummy_fp);
+  }
+
+start_push:
+
+  for (n = 0; n < HLSDEMUX2_STREAM_NUM; n++) {
+    cur_stream = demux->streams[n];
+
+    if (cur_stream && (stream != cur_stream)) {
+      cdisc = cur_stream->cdisc;
+    }
+  }
+
+  stream->nts = stop = stream->fts + demux->cfrag_dur;
+  stream->total_disc += cdisc;
+  stream->cdisc = cdisc;
+  next_ts = stream->fts;
+
+  GST_INFO_OBJECT (stream->pad, "Dummy video start_ts = %"GST_TIME_FORMAT" and stop_ts = %"GST_TIME_FORMAT,
+    GST_TIME_ARGS(stream->fts), GST_TIME_ARGS(stop));
+
+  /* set caps on buffer */
+  caps = gst_caps_new_simple ("video/x-h264",
+                  "stream-format", G_TYPE_STRING, "byte-stream",
+                  "alignment", G_TYPE_STRING, "nal",
+                  NULL);
+
+  gst_buffer_set_caps (buf, caps);
+
+  if (stream->need_newsegment) {
+    GST_INFO_OBJECT (stream->pad, "need to send new segment event based on audio");
+    g_queue_push_tail (stream->queue, (demux->streams[HLSDEMUX2_STREAM_AUDIO])->newsegment);
+    stream->need_newsegment = FALSE;
+  }
+
+  while (TRUE) {
+
+    if (demux->cancelled || demux->flushing) {
+      GST_WARNING_OBJECT (stream->pad, "Stopping dummy push task...");
+      goto quit;
+    }
+
+    g_mutex_lock (stream->queue_lock);
+
+    pushbuf = gst_buffer_copy (buf);
+    gst_buffer_set_caps (pushbuf, caps);
+    GST_BUFFER_TIMESTAMP (pushbuf) = stream->lts = next_ts;
+    GST_BUFFER_DURATION (pushbuf) = GST_CLOCK_TIME_NONE;
+
+    if (first_frame) {
+      GST_BUFFER_FLAG_SET (pushbuf, GST_BUFFER_FLAG_DISCONT);
+      first_frame = FALSE;
+    }
+
+    GST_LOG_OBJECT (stream->pad, "Pushing dummy buffer : ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (pushbuf)));
+
+    /* calculate cached duration */
+    gst_hlsdemux2_calculate_pushed_duration (demux, stream, pushbuf);
+
+    if (stream->cached_duration >= 0) {
+
+      percent = (stream->cached_duration * 100) / demux->total_cache_duration;
+      GST_LOG_OBJECT (stream->pad, "percent done = %"G_GINT64_FORMAT, percent);
+
+      if (percent > 100) {
+        guint64 overall_percent = 0;
+
+        g_mutex_lock (demux->buffering_lock);
+        overall_percent = demux->percent;
+        g_mutex_unlock (demux->buffering_lock);
+
+        if (overall_percent < 100) { /* otherwise, may cause blocking while buffering*/
+          GST_DEBUG_OBJECT (stream->pad, "@@@@@@@@@@@ queue should not go to wait now @@@@@@@@");
+        } else {
+          /* update buffering & wait if space is not available */
+          GST_DEBUG_OBJECT (stream->pad, "Reached more than 100 percent, queue full & wait till free");
+          g_cond_wait(stream->queue_full, stream->queue_lock);
+          GST_DEBUG_OBJECT (stream->pad,"Received signal to add more data...");
+        }
+      }
+    }
+
+    g_cond_signal (stream->queue_empty);
+
+    g_mutex_unlock (stream->queue_lock);
+
+    /* calculate next timestamp */
+    next_ts += HLS_DEFAULT_FRAME_DURATION;
+
+    if (next_ts > stop) {
+      GST_DEBUG_OBJECT (stream->pad, "Reached Endof the fragment ....\n\n");
+      break;
+    }
+  }
+
+  if (demux->end_of_playlist) {
+    /* end of playlist, push EOS to queue */
+    GST_INFO_OBJECT (stream->pad, "pushing EOS event to stream's queue");
+    g_queue_push_tail (stream->queue, gst_event_new_eos ());
+  }
+
+#ifdef LATEST_AV_SYNC
+  if (demux->is_live) {
+    stream->total_stream_time += (stream->lts - stream->fts);
+  } else {
+    stream->total_stream_time += (stream->lts - stream->fts + HLS_DEFAULT_FRAME_DURATION);
+    stream->total_stream_time = stream->nts;
+  }
+#else
+  stream->total_stream_time += (stream->lts - stream->fts);
+#endif
+
+  GST_DEBUG_OBJECT (stream->pad, "---------------- TS VALUES ----------------");
+  GST_DEBUG_OBJECT (stream->pad, "valid start ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->fts));
+  GST_DEBUG_OBJECT (stream->pad, "valid end ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->lts));
+  GST_DEBUG_OBJECT (stream->pad, "fragment duration received = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->lts - stream->fts));
+  GST_DEBUG_OBJECT (stream->pad, "total stream time = %"GST_TIME_FORMAT,GST_TIME_ARGS(stream->total_stream_time));
+  GST_DEBUG_OBJECT (stream->pad, "total disc time = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->total_disc));
+  GST_DEBUG_OBJECT (stream->pad, "next expected start ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->nts));
+  GST_DEBUG_OBJECT (stream->pad, "---------------- DUMP VALUES END----------------");
+
+  stream->apply_disc = FALSE;
+  stream->fts = GST_CLOCK_TIME_NONE;
+  stream->valid_fts_rcvd = FALSE;
+  stream->prev_nts = stream->nts;
+
+quit:
+  {
+    GST_INFO_OBJECT (stream->pad, "Stopping dummy data thread...");
+    gst_buffer_unref (buf);
+    stream->dummy_data_thread = NULL;
+    return TRUE;
+  }
+
+}
+
+static gboolean
+gst_hlsdemux2_sink_event_handler (GstPad * pad, GstEvent * event, gpointer data)
+{
+  GstHLSDemux2Stream *stream = (GstHLSDemux2Stream *)data;
+  GstHLSDemux2 *demux = stream->parent;
+
+  if ((GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) && stream->need_newsegment) {
+    GstEvent *newsegment = NULL;
+    GstFormat format;
+    gboolean update;
+    gdouble rate, arate;
+    gint64 start, stop, pos;
+
+    newsegment = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, demux->ns_start, -1, demux->ns_start);
+
+    GST_INFO_OBJECT (stream->pad, "Received NEWSEGMENT event...");
+
+    g_mutex_lock (stream->queue_lock);
+
+    gst_event_parse_new_segment_full(event, &update, &rate, &arate, &format, &start, &stop, &pos);
+
+    if (!GST_CLOCK_TIME_IS_VALID(stream->base_ts)) {
+      GST_INFO_OBJECT (stream->pad, "storing stream's base timestamp = %"GST_TIME_FORMAT, GST_TIME_ARGS(start));
+      stream->base_ts = start;
+    }
+
+    g_queue_push_tail (stream->queue, newsegment);
+
+    GST_INFO_OBJECT (stream->pad, "Pushed new segment event with start = %"GST_TIME_FORMAT" to queue..",
+      GST_TIME_ARGS(demux->ns_start));
+
+    g_mutex_unlock (stream->queue_lock);
+
+    stream->need_newsegment = FALSE;
+    stream->prev_nts = demux->ns_start;
+
+    if (stream->newsegment)
+      gst_event_unref (stream->newsegment);
+
+    stream->newsegment = gst_event_copy (newsegment);
+  }
+  return TRUE;
+}
+
+static gboolean
+hlsdemux2_HTTP_repeat_request (GstHLSDemux2 *demux, gchar *element_name)
+{
+  if (g_strrstr(element_name, "fragurisrc")) {
+    guint idx = 0;
+    GstBuffer *buf = NULL;
+
+    /* clear stream queues if we already downloaded some data */
+    for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+      GstHLSDemux2Stream *stream = demux->streams[idx];
+      if (stream ) {
+        while (!g_queue_is_empty (stream->downloader_queue)) {
+          buf = g_queue_pop_head (stream->downloader_queue);
+          gst_buffer_unref (buf);
+        }
+        GST_LOG_OBJECT (stream->pad, "cleared stream download queue...");
+        g_queue_clear (stream->downloader_queue);
+      }
+    }
+
+    /* request the same fragment again */
+    if (demux->fragCookie)
+      g_strfreev (demux->fragCookie);
+
+    g_object_get (demux->fdownloader->urisrc, "cookies", &demux->fragCookie, NULL);
+    GST_DEBUG_OBJECT (demux, "Got cookies after FRAGMENT download : %s", demux->fragCookie ? *(demux->fragCookie) : NULL);
+
+    GST_INFO_OBJECT (demux, "========>>>>>Going to download fragment AGAIN: %s", demux->frag_uri);
+
+    gst_hlsdemux2_destroy_fragment_download (demux);
+
+    if (!gst_hlsdemux2_create_fragment_download (demux, demux->frag_uri)) {
+      GST_ERROR_OBJECT (demux, "failed to create download pipeline");
+      GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
+      return FALSE;
+    }
+
+    /* download rate calculation : note down start time*/
+    demux->fdownloader->download_start_ts = gst_util_get_timestamp();
+
+    gst_element_set_state (demux->fdownloader->pipe, GST_STATE_PLAYING);
+
+    return TRUE;
+  } else if (g_strrstr(element_name, "playlisturisrc")) {
+
+    if (demux->playlistCookie)
+      g_strfreev (demux->playlistCookie);
+
+    g_object_get (demux->pldownloader->urisrc, "cookies", &demux->playlistCookie, NULL);
+
+    GST_DEBUG_OBJECT (demux, "Got cookies after PLAYLIST download : %s", demux->playlistCookie ? *(demux->playlistCookie) : NULL);
+
+    gst_hlsdemux2_destroy_playlist_download (demux);
+
+    GST_INFO_OBJECT (demux, "========>>>>>Going to download playlist AGAIN: %s", demux->playlist_uri);
+    if (!gst_hlsdemux2_create_playlist_download (demux, demux->playlist_uri)) {
+      GST_ERROR_OBJECT (demux, "failed to create download pipeline");
+      GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
+      return FALSE;
+    }
+
+    gst_element_set_state (demux->pldownloader->pipe, GST_STATE_PLAYING);
+    return TRUE;
+  } else if (g_strrstr(element_name, "keyurisrc")) {
+
+    if (demux->keyCookie)
+      g_strfreev (demux->keyCookie);
+
+    g_object_get (demux->kdownloader->urisrc, "cookies", &demux->keyCookie, NULL);
+
+    GST_DEBUG_OBJECT (demux, "Got cookies after KEY download : %s", demux->keyCookie ? *(demux->keyCookie) : NULL);
+
+    GST_INFO_OBJECT (demux, "========>>>>>Going to download key AGAIN: %s", demux->key_uri);
+
+    gst_hlsdemux2_destroy_key_download (demux);
+
+    if (!gst_hlsdemux2_create_key_download (demux, demux->key_uri)) {
+      GST_ERROR_OBJECT (demux, "failed to create download pipeline");
+      GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
+      return FALSE;
+    }
+
+    gst_element_set_state (demux->kdownloader->pipe, GST_STATE_PLAYING);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+
+static gboolean
+hlsdemux2_HTTP_time_out (GstHLSDemux2 *demux, gchar *element_name)
+{
+  if (g_strrstr(element_name, "fragurisrc")) {
+    /* as it is because of timeout, there is no point in requesting the same fragment again, so request next one */
+    GST_INFO_OBJECT (demux, "signalling fragment downloader to get next fragment...");
+    demux->fdownloader->get_next_frag = TRUE;
+    g_cond_signal (demux->fdownloader->cond);
+    return TRUE;
+  } else if (g_strrstr(element_name, "playlisturisrc")) {
+
+    if (demux->playlistCookie)
+      g_strfreev (demux->playlistCookie);
+
+    g_object_get (demux->pldownloader->urisrc, "cookies", &demux->playlistCookie, NULL);
+
+    GST_DEBUG_OBJECT (demux, "Got cookies after PLAYLIST download : %s", demux->playlistCookie ? *(demux->playlistCookie) : NULL);
+
+    gst_hlsdemux2_destroy_playlist_download (demux);
+
+    GST_INFO_OBJECT (demux, "========>>>>>Going to download playlist AGAIN: %s", demux->playlist_uri);
+    if (!gst_hlsdemux2_create_playlist_download (demux, demux->playlist_uri)) {
+      GST_ERROR_OBJECT (demux, "failed to create download pipeline");
+      GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
+      return FALSE;
+    }
+
+    gst_element_set_state (demux->pldownloader->pipe, GST_STATE_PLAYING);
+    return TRUE;
+  } else if (g_strrstr(element_name, "keyurisrc")) {
+
+    if (demux->keyCookie)
+      g_strfreev (demux->keyCookie);
+
+    g_object_get (demux->kdownloader->urisrc, "cookies", &demux->keyCookie, NULL);
+
+    GST_DEBUG_OBJECT (demux, "Got cookies after KEY download : %s", demux->keyCookie ? *(demux->keyCookie) : NULL);
+
+    GST_INFO_OBJECT (demux, "========>>>>>Going to download key AGAIN: %s", demux->key_uri);
+
+    gst_hlsdemux2_destroy_key_download (demux);
+
+    if (!gst_hlsdemux2_create_key_download (demux, demux->key_uri)) {
+      GST_ERROR_OBJECT (demux, "failed to create download pipeline");
+      GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
+      return FALSE;
+    }
+
+    gst_element_set_state (demux->kdownloader->pipe, GST_STATE_PLAYING);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+static gboolean
+hlsdemux2_HTTP_not_found(GstHLSDemux2 *demux, gchar *element_name)
+{
+  if (g_strrstr(element_name, "fragurisrc")) {
+    if (demux->is_live) {
+      /* request next fragment url */
+      GST_INFO_OBJECT (demux, "signalling fragment downloader to get next fragment...");
+      demux->fdownloader->get_next_frag = TRUE;
+      g_cond_signal (demux->fdownloader->cond);
+      return TRUE;
+    } else {
+
+#if 0 // In future enable
+      GList *next_variant = NULL;
+
+      if (demux->pldownloader->recovery_mode == HLSDEMUX2_NO_RECOVERY)
+        demux->pldownloader->recovery_mode = HLSDEMUX2_DOWNWARD_RECOVERY;
+
+      if (demux->pldownloader->recovery_mode == HLSDEMUX2_DOWNWARD_RECOVERY) {
+        /* get next available lower variant */
+        next_variant = gst_m3u8_client_get_next_lower_bw_playlist (demux->client);
+        if (!next_variant) {
+          GST_WARNING_OBJECT (demux, "no next lower variants.. Go Upward");
+          demux->pldownloader->recovery_mode = HLSDEMUX2_UPWARD_RECOVERY;
+        }
+      }
+
+      if (demux->pldownloader->recovery_mode == HLSDEMUX2_UPWARD_RECOVERY) {
+        /* get next available lower variant */
+        next_variant = gst_m3u8_client_get_next_higher_bw_playlist (demux->client);
+        if (!next_variant) {
+          GST_ERROR_OBJECT (demux, "no next higher variants.. need to exit");
+          demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
+          return FALSE;
+        }
+      }
+
+      /* change variant */
+      GST_M3U8_CLIENT_LOCK (demux->client);
+      demux->client->main->current_variant = next_variant;
+      GST_M3U8_CLIENT_UNLOCK (demux->client);
+
+      gst_m3u8_client_set_current (demux->client, next_variant->data);
+
+      demux->fdownloader->get_next_frag = TRUE;
+      g_cond_signal (demux->fdownloader->cond);
+
+      return TRUE;
+#else
+      return FALSE;
+#endif
+    }
+  } else if (g_strrstr(element_name, "playlisturisrc")) {
+    GList *next_variant = NULL;
+
+    if (demux->pldownloader->recovery_mode == HLSDEMUX2_NO_RECOVERY)
+      demux->pldownloader->recovery_mode = HLSDEMUX2_DOWNWARD_RECOVERY;
+
+    if (demux->pldownloader->recovery_mode == HLSDEMUX2_DOWNWARD_RECOVERY) {
+      /* get next available lower variant */
+      next_variant = gst_m3u8_client_get_next_lower_bw_playlist (demux->client);
+      if (!next_variant) {
+        GST_WARNING_OBJECT (demux, "no next lower variants.. Go Upward");
+        demux->pldownloader->recovery_mode = HLSDEMUX2_UPWARD_RECOVERY;
+      }
+    }
+
+    if (demux->pldownloader->recovery_mode == HLSDEMUX2_UPWARD_RECOVERY) {
+      /* get next available lower variant */
+      next_variant = gst_m3u8_client_get_next_higher_bw_playlist (demux->client);
+      if (!next_variant) {
+        GST_ERROR_OBJECT (demux, "no next higher variants.. need to exit");
+        demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
+        return FALSE;
+      }
+    }
+
+    /* change variant */
+    GST_M3U8_CLIENT_LOCK (demux->client);
+    demux->client->main->current_variant = next_variant;
+    GST_M3U8_CLIENT_UNLOCK (demux->client);
+
+    gst_m3u8_client_set_current (demux->client, next_variant->data);
+
+    /* get new playlist uri */
+    demux->playlist_uri = g_strdup (gst_m3u8_client_get_current_uri (demux->client));
+
+    if (demux->playlistCookie)
+      g_strfreev (demux->playlistCookie);
+
+    g_object_get (demux->pldownloader->urisrc, "cookies", &demux->playlistCookie, NULL);
+
+    GST_DEBUG_OBJECT (demux, "Got cookies after PLAYLIST download : %s", demux->playlistCookie ? *(demux->playlistCookie) : NULL);
+
+    gst_hlsdemux2_destroy_playlist_download (demux);
+
+    GST_INFO_OBJECT (demux, "========>>>>>Going to download recovery playlist : %s", demux->playlist_uri);
+    if (!gst_hlsdemux2_create_playlist_download (demux, demux->playlist_uri)) {
+      GST_ERROR_OBJECT (demux, "failed to create download pipeline");
+      GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
+      return FALSE;
+    }
+
+    gst_element_set_state (demux->pldownloader->pipe, GST_STATE_PLAYING);
+
+    return TRUE;
+
+  } else if (g_strrstr(element_name, "keyurisrc")) {
+    /* treating it as non-recoverable error */
+    return FALSE;
+  }
+
+  return FALSE;
+}
+
+static gboolean
+gst_hlsdemux2_handle_HTTP_error (GstHLSDemux2 *demux, GError *error, gchar *element_name) {
+  guint i = 0;
+  guint n_http_errors = sizeof (http_errors) / sizeof (http_errors[0]);
+
+  if(!error)
+    return HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE;
+  for (i = 0; i < n_http_errors; i++) {
+    if (G_LIKELY (!strncmp(error->message, http_errors[i].error_phrase, strlen(error->message)))) {
+      if (http_errors[i].handle_error) {
+        return http_errors[i].handle_error (demux, element_name);
+      }
+      return http_errors[i].error_type;
+    }
+  }
+  return HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE;
+}
+
+static gboolean
+gst_hlsdemux2_fragment_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
+{
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
+  GError *error = NULL;
+  gchar* debug = NULL;
+  gboolean bret = TRUE;
+  GstMessage *err_msg = NULL;
+  gchar *ele_name = gst_element_get_name (GST_MESSAGE_SRC (msg));
+
+  switch (GST_MESSAGE_TYPE(msg)) {
+    case GST_MESSAGE_EOS: {
+      GST_INFO_OBJECT (demux, "received EOS on download pipe from '%s'..", ele_name);
+      demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
+      g_cond_signal(demux->fdownloader->cond);
+      break;
+    }
+    case GST_MESSAGE_ERROR: {
+      GST_ERROR_OBJECT (demux, "Error from %s\n", ele_name);
+
+      gst_message_parse_error( msg, &error, &debug );
+
+      demux->fdownloader->error_rcvd = TRUE;
+
+      if (error)
+        GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: error->message = %s and error->code = %d", error->message);
+
+      GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: debug = %s", debug);
+
+      if (g_strrstr(ele_name, "fragurisrc") && !demux->cancelled && demux->soup_request_fail_cnt) {
+
+        /* flush the error msgs pending.. as we are going to create new pipeline */
+        gst_bus_set_flushing (bus, TRUE);
+
+        bret = gst_hlsdemux2_handle_HTTP_error (demux, error, ele_name);
+        if (!bret)
+          goto post_error;
+        else {
+          demux->soup_request_fail_cnt--;
+          GST_WARNING_OBJECT (demux, "HTTP error count remaining = %d", demux->soup_request_fail_cnt);
+          goto exit;
+        }
+      }
+
+post_error:
+
+      GST_ERROR_OBJECT (demux, "posting error from fragment download callback");
+
+      err_msg = gst_message_new_error (GST_OBJECT(demux), error, debug);
+      if (!gst_element_post_message (GST_ELEMENT(demux), err_msg)) {
+        GST_ERROR_OBJECT (demux, "failed to post error");
+        bret = FALSE;
+        goto exit;
+      }
+      gst_hlsdemux2_stop (demux);
+      break;
+    }
+    case GST_MESSAGE_WARNING: {
+      gst_message_parse_warning(msg, &error, &debug);
+      GST_WARNING_OBJECT(demux, "warning : %s\n", error->message);
+      GST_WARNING_OBJECT(demux, "debug : %s\n", debug);
+      break;
+    }
+    case GST_MESSAGE_ELEMENT: {
+      const GstStructure *s = gst_message_get_structure (msg);
+
+      if (gst_structure_has_name (s, "cookies")) {
+        const GValue *value;
+        gchar **cookies = NULL;
+        gchar *cookie = NULL;
+        value = gst_structure_get_value (s, "cookies");
+        cookie = g_strdup_value_contents(value);
+
+        cookies = &cookie;
+        GST_ERROR_OBJECT (demux, "received cookies from soup : %s", *cookies);
+      }
+      break;
+    }
+    default : {
+      break;
+    }
+  }
+
+exit:
+  if (debug)
+    g_free( debug);
+
+  if (error)
+    g_error_free( error);
+
+  if (!bret)
+    gst_hlsdemux2_stop (demux);
+
+  g_free (ele_name);
+
+  return bret;
+}
+
+static GstBusSyncReply
+gst_hlsdemux2_playlist_download_bus_sync_cb (GstBus * bus, GstMessage *msg, gpointer data)
+{
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
+  GstBusSyncReply reply = GST_BUS_DROP;
+
+  GError *error = NULL;
+  gchar *debug = NULL;
+  gboolean bret = TRUE;
+  GstMessage *err_msg = NULL;
+  gchar *ele_name = gst_element_get_name (GST_MESSAGE_SRC (msg));
+
+  switch (GST_MESSAGE_TYPE(msg)) {
+    case GST_MESSAGE_EOS: {
+      GST_DEBUG_OBJECT (demux, "received EOS on playlist download pipe..");
+      demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
+      g_mutex_lock (demux->pldownloader->lock);
+      g_cond_broadcast (demux->pldownloader->cond);
+      g_mutex_unlock (demux->pldownloader->lock);
+      break;
+    }
+    case GST_MESSAGE_ERROR: {
+      GST_ERROR_OBJECT (demux, "Error from %s element", ele_name);
+
+      gst_message_parse_error( msg, &error, &debug );
+      if (error)
+        GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: error= %s", error->message);
+
+      GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: debug = %s", debug);
+
+      if (g_strrstr(ele_name, "playlisturisrc") && !demux->cancelled && demux->soup_request_fail_cnt) {
+
+        /* flush the error msgs pending.. as we are going to create new pipeline */
+        gst_bus_set_flushing (bus, TRUE);
+
+        bret = gst_hlsdemux2_handle_HTTP_error (demux, error, ele_name);
+        if (!bret)
+          goto post_error;
+        else {
+          demux->soup_request_fail_cnt--;
+          GST_WARNING_OBJECT (demux, "HTTP error count remaining = %d", demux->soup_request_fail_cnt);
+          goto exit;
+        }
+      }
+
+post_error:
+
+      GST_ERROR_OBJECT (demux, "posting error from playlist callback...");
+
+      err_msg = gst_message_new_error (GST_OBJECT(demux), error, debug);
+      if (!gst_element_post_message (GST_ELEMENT(demux), err_msg)) {
+        GST_ERROR_OBJECT (demux, "failed to post error");
+        bret = FALSE;
+        goto exit;
+      }
+      gst_hlsdemux2_stop (demux);
+      break;
+    }
+    case GST_MESSAGE_WARNING: {
+      gst_message_parse_warning(msg, &error, &debug);
+      if (error)
+        GST_WARNING_OBJECT(demux, "warning : %s\n", error->message);
+      GST_WARNING_OBJECT(demux, "debug : %s\n", debug);
+      break;
+    }
+    case GST_MESSAGE_ELEMENT: {
+      const GstStructure *s = gst_message_get_structure (msg);
+
+      if (gst_structure_has_name (s, "cookies")) {
+        const GValue *value;
+        gchar **cookies = NULL;
+        gchar *cookie = NULL;
+        value = gst_structure_get_value (s, "cookies");
+        cookie = g_strdup_value_contents(value);
+
+        cookies = &cookie;
+        GST_ERROR_OBJECT (demux, "received cookies from soup : %s", *cookies);
+      }
+      break;
+    }
+    default : {
+      //GST_LOG_OBJECT(demux, "unhandled message : %s\n", gst_message_type_get_name (GST_MESSAGE_TYPE (msg)));
+      break;
+    }
+  }
+
+exit:
+  if (debug)
+    g_free( debug);
+
+  if (error)
+    g_error_free( error);
+
+  if (!bret)
+    gst_hlsdemux2_stop (demux);
+
+  g_free (ele_name);
+
+  return reply;
+}
+
+static gboolean
+gst_hlsdemux2_key_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
+{
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
+  GError *error = NULL;
+  gchar* debug = NULL;
+  gboolean bret = TRUE;
+  GstMessage *err_msg = NULL;
+  gchar *ele_name = gst_element_get_name (GST_MESSAGE_SRC (msg));
+
+  switch (GST_MESSAGE_TYPE(msg)) {
+    case GST_MESSAGE_EOS: {
+      GST_DEBUG_OBJECT (demux, "received EOS on key download pipe..");
+      demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
+      g_mutex_lock (demux->kdownloader->lock);
+      g_cond_signal (demux->kdownloader->cond);
+      g_mutex_unlock (demux->kdownloader->lock);
+      break;
+    }
+    case GST_MESSAGE_ERROR: {
+      GST_INFO_OBJECT (demux, "Error from %s element...", ele_name);
+
+      gst_message_parse_error(msg, &error, &debug);
+
+      if (error)
+        GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: error= %s", error->message);
+
+      GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: debug = %s", debug);
+
+      if (g_strrstr(ele_name, "keyurisrc") && !demux->cancelled && demux->soup_request_fail_cnt) {
+
+        /* flush the error msgs pending.. as we are going to create new pipeline */
+        gst_bus_set_flushing (bus, TRUE);
+
+        bret = gst_hlsdemux2_handle_HTTP_error (demux, error, ele_name);
+        if (!bret)
+          goto post_error;
+        else {
+          demux->soup_request_fail_cnt--;
+          GST_WARNING_OBJECT (demux, "HTTP error count remaining = %d", demux->soup_request_fail_cnt);
+          goto exit;
+        }
+      }
+
+post_error:
+      GST_ERROR_OBJECT (demux, "Error posting from key downloader...");
+      err_msg = gst_message_new_error (GST_OBJECT(demux), error, debug);
+
+      if (!gst_element_post_message (GST_ELEMENT(demux), err_msg)) {
+        GST_ERROR_OBJECT (demux, "failed to post error");
+        gst_hlsdemux2_stop (demux);
+        bret = FALSE;
+        goto exit;
+      }
+      gst_hlsdemux2_stop (demux);
+      break;
+    }
+    case GST_MESSAGE_WARNING: {
+      gst_message_parse_warning(msg, &error, &debug);
+      if (error)
+        GST_WARNING_OBJECT(demux, "warning : %s\n", error->message);
+      GST_WARNING_OBJECT(demux, "debug : %s\n", debug);
+      break;
+    }
+    case GST_MESSAGE_ELEMENT: {
+      const GstStructure *s = gst_message_get_structure (msg);
+
+      if (gst_structure_has_name (s, "cookies")) {
+        const GValue *value;
+        gchar **cookies = NULL;
+        gchar *cookie = NULL;
+        value = gst_structure_get_value (s, "cookies");
+        cookie = g_strdup_value_contents(value);
+
+        cookies = &cookie;
+        GST_ERROR_OBJECT (demux, "received cookies from soup : %s", *cookies);
+      }
+     break;
+    }
+    default : {
+      break;
+    }
+  }
+
+exit:
+
+  if (debug)
+    g_free( debug);
+
+  if (error)
+    g_error_free( error);
+
+  if (!bret)
+    gst_hlsdemux2_stop (demux);
+
+  g_free (ele_name);
+
+  return bret;
+}
+
+static void
+gst_hlsdemux2_calculate_pushed_duration (GstHLSDemux2 *demux, GstHLSDemux2Stream *stream,
+    GstBuffer *inbuf)
+{
+  gint len = 0;
+  int qidx = 0;
+  gpointer data = NULL;
+
+  // TODO: for all timestamps -1 case, we need to add max-bytes also
+
+  g_queue_push_tail (stream->queue, inbuf);
+
+  len = g_queue_get_length (stream->queue);
+
+  /* peek the head buffer having valid timestamp to calculate cached duration */
+  while (qidx < len) {
+    data = g_queue_peek_nth (stream->queue, qidx);
+
+    if (GST_IS_BUFFER (data)) {
+      if (GST_BUFFER_TIMESTAMP_IS_VALID(data)) {
+        GST_LOG_OBJECT (stream->pad, "data found buffer with valid ts = %"GST_TIME_FORMAT " len = %d & qidx = %d",
+          GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(data)), len, qidx);
+        break;
+      }
+    }
+    qidx++;
+  }
+  if(GST_IS_BUFFER (data)) {
+    if (GST_BUFFER_TIMESTAMP (inbuf) >= GST_BUFFER_TIMESTAMP ((GstBuffer *)data)) {
+      stream->cached_duration = GST_BUFFER_TIMESTAMP (inbuf) - GST_BUFFER_TIMESTAMP ((GstBuffer *)data);
+      GST_LOG_OBJECT (stream->pad, "len = %d, cached duration = %"GST_TIME_FORMAT,
+          g_queue_get_length (stream->queue), GST_TIME_ARGS(stream->cached_duration));
+    } else {
+      GST_WARNING_OBJECT (stream->pad, "Wrong order.. not calculating");
+    }
+  }
+  return;
+}
+
+static gboolean
+gst_hlsdemux2_alter_timestamps (GstHLSDemux2Stream *stream, GstBuffer *inbuf)
+{
+  GstHLSDemux2 *demux = stream->parent;
+  GstClockTime cts = 0;
+
+  /* set discontinuity only when there is real fragment discontinuity */
+  if (GST_BUFFER_IS_DISCONT(inbuf)) {
+    if (!stream->apply_disc) {
+      GST_BUFFER_FLAG_UNSET (inbuf, GST_BUFFER_FLAG_DISCONT);
+      GST_INFO_OBJECT (stream->pad, "unsetting discontinuity flag...");
+    }
+  }
+
+  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (inbuf))) {
+    if (GST_BUFFER_TIMESTAMP (inbuf) >= stream->base_ts) {
+      cts = GST_BUFFER_TIMESTAMP (inbuf) - stream->base_ts;
+    } else {
+      /* this buffer should be dropped at sink */
+      GST_WARNING_OBJECT (stream->pad, "input timestamp [%"GST_TIME_FORMAT"] is less than base_ts [%"GST_TIME_FORMAT"]",
+        GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (inbuf)), GST_TIME_ARGS(stream->base_ts));
+      if (stream->type == HLSDEMUX2_STREAM_AUDIO) {
+        return FALSE;
+      } else {
+        GST_BUFFER_TIMESTAMP (inbuf) = GST_CLOCK_TIME_NONE;
+        return TRUE;
+      }
+    }
+  } else {
+    /* this buffer should be dropped at sink */
+    GST_LOG_OBJECT (stream->pad, "invalid input timestamp (i.e. GST_CLOCK_TIME_NONE)");
+#ifdef LATEST_AV_SYNC
+    if (!demux->is_live && (stream->type == HLSDEMUX2_STREAM_AUDIO) && !stream->valid_fts_rcvd){
+      GST_WARNING_OBJECT (stream->pad, "dropping invalid ts buffer, due to no valid first ts yet...");
+      return FALSE;
+    }
+#endif
+    return TRUE;
+  }
+
+  /* handle discontinuity in stream */
+  if(GST_CLOCK_TIME_IS_VALID (stream->nts) && (GST_CLOCK_DIFF(stream->nts,cts) > (2 * GST_SECOND)) && stream->apply_disc) {
+    GST_INFO_OBJECT (stream->pad, "cts = %"GST_TIME_FORMAT" and prev_next_ts = %"GST_TIME_FORMAT,
+      GST_TIME_ARGS(cts), GST_TIME_ARGS(stream->nts));
+    GST_INFO_OBJECT (stream->pad,"Received disc = %"GST_TIME_FORMAT, GST_TIME_ARGS(cts - stream->nts));
+    stream->cdisc = cts - stream->nts;
+    stream->total_disc += (cts - stream->nts);
+    GST_INFO_OBJECT (stream->pad, "total disc = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->total_disc));
+    stream->apply_disc = FALSE;
+  }
+
+  cts -= stream->cdisc;
+
+  /* get the max last ts, required because of frame reordering */
+  stream->lts = cts > stream->lts ? cts : stream->lts;
+
+  GST_DEBUG_OBJECT (stream->pad, "modifying buffer timestamp : %"GST_TIME_FORMAT" -> %"GST_TIME_FORMAT,
+    GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (inbuf)), GST_TIME_ARGS(cts));
+
+#ifndef LATEST_AV_SYNC
+  /* store first valid timestamp of a fragment */
+  if (stream->fts == GST_CLOCK_TIME_NONE) {
+    stream->fts = cts;
+    stream->nts = stream->fts + demux->cfrag_dur;
+    GST_INFO_OBJECT (stream->pad, "storing first ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->fts));
+    if (demux->is_live && stream->type == HLSDEMUX2_STREAM_AUDIO)
+      demux->cur_audio_fts = cts;
+  }
+#endif
+
+#ifdef LATEST_AV_SYNC
+       /* 10/31/2013: dont want to disturb live case at this moment */
+  if (!stream->valid_fts_rcvd) {
+    if (stream->type == HLSDEMUX2_STREAM_AUDIO) {
+      if (!demux->is_live && (GST_CLOCK_DIFF(cts, stream->prev_nts) > (10 * GST_MSECOND))) {
+        GST_WARNING_OBJECT (stream->pad, "already seen audio timestamps[%"GST_TIME_FORMAT"]"
+          " and previous_nts = %"GST_TIME_FORMAT"...drop this",
+          GST_TIME_ARGS(cts), GST_TIME_ARGS(stream->prev_nts));
+        return FALSE;
+      } else {
+        GST_INFO_OBJECT (stream->pad, "recevied valid audio first ts = %"GST_TIME_FORMAT,
+          GST_TIME_ARGS (cts));
+        demux->cur_audio_fts = cts;
+      }
+    }
+
+    stream->valid_fts_rcvd = TRUE;
+    stream->fts = cts;
+    stream->nts = stream->fts + demux->cfrag_dur; // Approximate nts
+
+    GST_INFO_OBJECT (stream->pad, "storing first ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->fts));
+  } else if (!stream->frame_duration) {
+    stream->frame_duration = cts - stream->fts;
+    GST_DEBUG_OBJECT (stream->pad, "frame duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->frame_duration));
+  }
+
+#else
+
+  /* 10/31/2013: dont want to disturb live case at this moment */
+  if (!demux->is_live && stream->type == HLSDEMUX2_STREAM_AUDIO) {
+    if (!stream->valid_fts_rcvd) {
+      if (GST_CLOCK_DIFF(cts, stream->prev_nts) > 0) {
+        GST_WARNING_OBJECT (stream->pad, "already seen audio timestamps[%"GST_TIME_FORMAT"]"
+          " and previous_nts = %"GST_TIME_FORMAT"...drop this",
+          GST_TIME_ARGS(cts), GST_TIME_ARGS(stream->prev_nts));
+        return FALSE;
+      } else {
+        GST_INFO_OBJECT (stream->pad, "recevied valid audio first ts = %"GST_TIME_FORMAT,
+          GST_TIME_ARGS (cts));
+        demux->cur_audio_fts = cts;
+        stream->valid_fts_rcvd = TRUE;
+      }
+    } else if (!stream->frame_duration) {
+      stream->frame_duration = cts - demux->cur_audio_fts;
+      GST_DEBUG_OBJECT (demux, "audio frame duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->frame_duration));
+    }
+  }
+#endif
+
+  GST_BUFFER_TIMESTAMP (inbuf) = cts;
+
+  return TRUE;
+}
+
+static void
+gst_hlsdemux2_downloader_new_buffer (GstElement *appsink, void *user_data)
+{
+  GstHLSDemux2Stream *stream = (GstHLSDemux2Stream *)user_data;
+  GstHLSDemux2 *demux = stream->parent;
+  GstBuffer *inbuf = NULL;
+  gboolean bret = FALSE;
+
+  if (demux->cancelled ) {
+    return;
+  }
+
+  inbuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
+  if (!inbuf) {
+    GST_WARNING_OBJECT (demux, "Input buffer not available...");
+    return;
+  }
+
+  GST_LOG_OBJECT (stream->pad, "Received buffer with size = %d and ts = %"GST_TIME_FORMAT,
+    GST_BUFFER_SIZE(inbuf), GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(inbuf)));
+
+  if (demux->fdownloader->force_timestamps) {
+    GST_BUFFER_TIMESTAMP(inbuf) += (stream->prev_nts + stream->base_ts);
+    GST_DEBUG_OBJECT (stream->pad, "forced timestamp = %"GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(inbuf)));
+  }
+
+  /* alter the timestamps */
+  bret = gst_hlsdemux2_alter_timestamps (stream, inbuf);
+  if (!bret) {
+    gst_buffer_unref (inbuf);
+    return;
+  }
+
+  /* store buffer in queue */
+  g_queue_push_tail (stream->downloader_queue, inbuf);
+
+  return;
+}
+
+static gboolean
+gst_hlsdemux2_imagebuf_pipe_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
+{
+  GstHLSDemux2PvtStream *stream = (GstHLSDemux2PvtStream *)data;
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)stream->parent;
+  gboolean bret = TRUE;
+  gchar *ele_name = gst_element_get_name (GST_MESSAGE_SRC (msg));
+
+  GST_INFO_OBJECT(demux, "Message on BUS : %s", gst_message_type_get_name(GST_MESSAGE_TYPE(msg)));
+  switch (GST_MESSAGE_TYPE(msg)) {
+    case GST_MESSAGE_EOS: {
+      GST_INFO_OBJECT (demux, "received EOS on IMAGE pipe from '%s'.. Closing pipeline", ele_name);
+      g_cond_signal (stream->convert_cond);
+      gst_object_unref (stream->convert_pipe);
+      break;
+    }
+    case GST_MESSAGE_ERROR: {
+      GST_ERROR_OBJECT (demux, "Error Image Pipe from %s\n", ele_name);
+      bret = FALSE;
+      break;
+    }
+    default:{
+      GST_DEBUG_OBJECT (demux, "Message on Image Pipe : %s from %s\n", gst_message_type_get_name(GST_MESSAGE_TYPE(msg)), ele_name);
+      bret = FALSE;
+      break;
+    }
+  }
+  g_free(ele_name);
+  ele_name = NULL;
+  return bret;
+}
+
+static gboolean gst_hlsdemux2_done_video_buffer (GstPad * srcpad, GstEvent * event, gpointer user_data)
+{
+  GstHLSDemux2PvtStream *stream = (GstHLSDemux2PvtStream *)user_data;
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)stream->parent;
+  GST_LOG_OBJECT(demux,"EVENT %s on pad : %s having caps : %"GST_PTR_FORMAT,GST_EVENT_TYPE_NAME (event), GST_PAD_NAME(srcpad), srcpad->caps);
+  if(event->type == GST_EVENT_EOS){
+    GST_DEBUG_OBJECT(demux,"EVENT : %s Size : %d Pushing to demux video buffer [%d,%d]",
+    GST_EVENT_TYPE_NAME (event),GST_BUFFER_SIZE(stream->video_buffer),
+        stream->video_buffer->data[0],stream->video_buffer->data[1]);
+    g_cond_signal (stream->convert_cond);
+  }
+  return TRUE;
+}
+
+static gboolean gst_hlsdemux2_set_video_buffer (GstPad * srcpad, GstBuffer * buffer, gpointer user_data)
+{
+  GstHLSDemux2PvtStream *pvt_stream = (GstHLSDemux2PvtStream *)user_data;
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)pvt_stream->parent;
+  GST_LOG_OBJECT(demux,"BUFFER size:%d on pad having caps : %"GST_PTR_FORMAT,GST_BUFFER_SIZE(buffer), srcpad->caps);
+  GST_LOG_OBJECT(demux,"BUFFER DATA : %d %d",buffer->data[0],buffer->data[1]);
+  pvt_stream->video_buffer = buffer;
+  return TRUE;
+}
+
+static void
+gst_hlsdemux2_downloader_eos (GstElement * appsink, void* user_data)
+{
+  GstHLSDemux2Stream *stream = (GstHLSDemux2Stream *)user_data;
+  GstHLSDemux2 *demux = stream->parent;
+  GstBuffer *buf = NULL;
+  gint64 percent = 0;
+
+  /* push all data to queue specific to this stream */
+
+  if (demux->cancelled || demux->flushing) {
+    GST_WARNING_OBJECT (demux, "returning due to cancelled / flushing");
+    return;
+  }
+
+  if (g_queue_is_empty (stream->downloader_queue)) {
+    GST_WARNING_OBJECT (demux, "EOS received without any buffer in downloader queue");
+    return;
+  }
+
+  if (demux->fdownloader->force_timestamps) {
+    demux->cur_audio_fts = stream->prev_nts;
+  }
+
+  if (demux->fdownloader->cur_stream_cnt < demux->active_stream_cnt) {
+    gint idx = 0;
+
+    GST_INFO_OBJECT (demux, "need to send dummy data.. check for the stream");
+
+    /* signal queue full condition to come out */
+    for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+      GstHLSDemux2Stream *cur_stream = demux->streams[idx];
+      GError *error = NULL;
+
+      if (cur_stream) {
+        if (g_queue_is_empty (cur_stream->downloader_queue)) {
+          GST_INFO_OBJECT (cur_stream->pad, "enable sending dummy data");
+
+          /* take first ts of audio as cur_stream fts */
+          cur_stream->fts = demux->cur_audio_fts;
+
+          /* create thread to send dummy data */
+          cur_stream->dummy_data_thread = g_thread_create ((GThreadFunc) gst_hlsdemux2_push_dummy_data,
+            cur_stream, TRUE, &error);
+        }
+      }
+    }
+  }
+
+  while (!g_queue_is_empty (stream->downloader_queue)) {
+
+    if (demux->cancelled || demux->flushing) {
+      GST_WARNING_OBJECT (stream->pad, "on cancel/flushing stopping pushing");
+      break;
+    }
+
+    buf = (GstBuffer *) g_queue_pop_head (stream->downloader_queue);
+
+    GST_DEBUG_OBJECT (stream->pad, "input buffer timestamp : %"GST_TIME_FORMAT,
+      GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (buf)));
+
+    g_mutex_lock (stream->queue_lock);
+
+    if (!GST_BUFFER_TIMESTAMP_IS_VALID(buf)){
+      g_queue_push_tail (stream->queue, buf);
+      g_cond_signal (stream->queue_empty);
+      g_mutex_unlock (stream->queue_lock);
+      continue;
+    }
+
+    GST_LOG_OBJECT (stream->pad, "buffer size = %d, ts = %"GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT,
+      GST_BUFFER_SIZE(buf), GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buf)), GST_TIME_ARGS(GST_BUFFER_DURATION(buf)));
+
+    /* calculate cached duration */
+    gst_hlsdemux2_calculate_pushed_duration (demux, stream, buf);
+
+    if (stream->cached_duration < 0)
+      stream->cached_duration = 0;
+
+    percent = (stream->cached_duration * 100) / demux->total_cache_duration;
+    GST_LOG_OBJECT (stream->pad, "percent done = %"G_GINT64_FORMAT, (gint)percent, percent);
+
+    if (percent > 100) {
+      guint64 overall_percent = 0;
+
+      g_mutex_lock (demux->buffering_lock);
+      overall_percent = demux->percent;
+      g_mutex_unlock (demux->buffering_lock);
+
+      if (overall_percent < 100) { /* otherwise, may cause blocking while buffering*/
+        if (percent > 400) {
+          GST_ERROR_OBJECT (stream->pad,"having worrest buffering.. exiting");
+          GST_ELEMENT_ERROR (demux, STREAM, FAILED, ("wrong buffering.. check implementation"), (NULL));
+        }
+        GST_INFO_OBJECT (stream->pad, "@@@@@@ queue should not go to wait now @@@@@@@@");
+      } else {
+        /* update buffering & wait if space is not available */
+        GST_LOG_OBJECT (stream->pad, "Reached more than 100 percent, queue full & wait till free");
+        g_cond_wait(stream->queue_full, stream->queue_lock);
+        GST_LOG_OBJECT (stream->pad,"Received signal to add more data...");
+      }
+    }
+
+    g_cond_signal (stream->queue_empty);
+
+    g_mutex_unlock (stream->queue_lock);
+  }
+
+  /* wait for dummy threads finish their processing */
+  if (demux->fdownloader->cur_stream_cnt < demux->active_stream_cnt) {
+    gint idx = 0;
+
+    GST_INFO_OBJECT (demux, "need to close dummy threads");
+
+    /* signal queue full condition to come out */
+    for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+      GstHLSDemux2Stream *cur_stream = demux->streams[idx];
+
+      if (cur_stream && cur_stream->dummy_data_thread) {
+        GST_INFO_OBJECT (stream->pad, "waiting for dummy push thread to finish...");
+        g_thread_join(cur_stream->dummy_data_thread);
+        cur_stream->dummy_data_thread = NULL;
+        GST_INFO_OBJECT (stream->pad, "COMPLETED DUMMY PUSH...");
+      }
+    }
+  }
+
+#ifdef LATEST_AV_SYNC
+  if (demux->is_live) {
+    stream->total_stream_time += (stream->lts - stream->fts);
+  } else {
+    stream->total_stream_time += (stream->lts - stream->fts + stream->frame_duration);
+    stream->nts = stream->total_stream_time;
+  }
+#else
+  stream->total_stream_time += (stream->lts - stream->fts);
+#endif
+
+  GST_DEBUG_OBJECT (stream->pad, "---------------- TS VALUES ----------------");
+  GST_DEBUG_OBJECT (stream->pad, "valid start ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->fts));
+  GST_DEBUG_OBJECT (stream->pad, "valid end ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->lts));
+  GST_DEBUG_OBJECT (stream->pad, "fragment duration received = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->lts - stream->fts));
+  GST_DEBUG_OBJECT (stream->pad, "total stream time = %"GST_TIME_FORMAT,GST_TIME_ARGS(stream->total_stream_time));
+  GST_DEBUG_OBJECT (stream->pad, "total disc time = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->total_disc));
+  GST_DEBUG_OBJECT (stream->pad, "next expected start ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->nts));
+  GST_DEBUG_OBJECT (stream->pad, "---------------- DUMP VALUES END----------------");
+
+  stream->apply_disc = FALSE;
+  stream->fts = GST_CLOCK_TIME_NONE;
+  stream->valid_fts_rcvd = FALSE;
+  stream->prev_nts = stream->nts;
+  demux->fdownloader->force_timestamps = FALSE;
+  return;
+}
+
+static void
+gst_hlsdemux2_push_eos (GstHLSDemux2 *demux)
+{
+  guint idx = 0;
+
+  /* signal queue full condition to come out */
+  for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+    GstHLSDemux2Stream *stream = demux->streams[idx];
+
+    if (stream) {
+      g_mutex_lock (stream->queue_lock);
+      /* end of playlist, push EOS to queue */
+      GST_INFO_OBJECT (stream->pad, "pushing EOS event to stream's queue");
+      g_queue_push_tail (stream->queue, gst_event_new_eos ());
+      g_cond_signal (stream->queue_empty);
+      g_mutex_unlock (stream->queue_lock);
+    }
+  }
+}
+
+static void
+gst_hlsdemux2_on_playlist_buffer (GstElement *appsink, void *data)
+{
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
+  GstBuffer *inbuf = NULL;
+
+  inbuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
+  if (!inbuf) {
+    GST_WARNING_OBJECT (demux, "Input buffer not available...");
+    return;
+  }
+
+  if (demux->pldownloader->playlist == NULL) {
+    demux->pldownloader->playlist = gst_buffer_copy (inbuf);
+    gst_buffer_unref (inbuf);
+  } else {
+    GstBuffer *buffer = NULL;
+    guint size = GST_BUFFER_SIZE(demux->pldownloader->playlist) + GST_BUFFER_SIZE(inbuf);
+
+    buffer = gst_buffer_new_and_alloc (size);
+    if (!buffer) {
+      GST_ERROR_OBJECT (demux, "failed allocate memory...");
+      GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
+      gst_buffer_unref (inbuf);
+      gst_buffer_unref (demux->pldownloader->playlist);
+      return;
+    }
+
+    /*copy existing playlist buffer */
+    memcpy (GST_BUFFER_DATA(buffer), GST_BUFFER_DATA(demux->pldownloader->playlist), GST_BUFFER_SIZE(demux->pldownloader->playlist));
+
+    /*copy new playlist buffer */
+    memcpy (GST_BUFFER_DATA(buffer) + GST_BUFFER_SIZE(demux->pldownloader->playlist),
+        GST_BUFFER_DATA(inbuf), GST_BUFFER_SIZE(inbuf));
+
+    gst_buffer_unref (inbuf);
+    gst_buffer_unref (demux->pldownloader->playlist);
+    demux->pldownloader->playlist = buffer;
+  }
+
+  return;
+}
+
+static void
+gst_hlsdemux2_on_key_buffer (GstElement *appsink, void *data)
+{
+  GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
+  GstBuffer *inbuf = NULL;
+
+  inbuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
+  if (!inbuf) {
+    GST_WARNING_OBJECT (demux, "Input buffer not available...");
+    return;
+  }
+
+  if (demux->kdownloader->key == NULL) {
+    demux->kdownloader->key = gst_buffer_copy (inbuf);
+    gst_buffer_unref (inbuf);
+  } else {
+    GstBuffer *buffer = NULL;
+    guint size = GST_BUFFER_SIZE(demux->kdownloader->key) + GST_BUFFER_SIZE(inbuf);
+
+    buffer = gst_buffer_new_and_alloc (size);
+    if (!buffer) {
+      GST_ERROR_OBJECT (demux, "failed allocate memory...");
+      GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
+      gst_buffer_unref (inbuf);
+      gst_buffer_unref (demux->kdownloader->key);
+      return;
+    }
+
+    /*copy existing playlist buffer */
+    memcpy (GST_BUFFER_DATA(buffer), GST_BUFFER_DATA(demux->kdownloader->key), GST_BUFFER_SIZE(demux->kdownloader->key));
+
+    /*copy new playlist buffer */
+    memcpy (GST_BUFFER_DATA(buffer) + GST_BUFFER_SIZE(demux->kdownloader->key),
+        GST_BUFFER_DATA(inbuf), GST_BUFFER_SIZE(inbuf));
+
+    gst_buffer_unref (inbuf);
+    gst_buffer_unref (demux->kdownloader->key);
+    demux->kdownloader->key = buffer;
+  }
+
+  return;
+}
+
+static void
+gst_hlsdemux2_stop (GstHLSDemux2 *demux)
+{
+  GST_INFO_OBJECT (demux, "entering...");
+
+  demux->cancelled = TRUE;
+
+  g_cond_signal (demux->post_msg_start);
+  g_cond_signal (demux->post_msg_exit);
+
+  /* special case: for exiting playlist downloader created from sink event */
+  if (demux->pldownloader && demux->pldownloader->cond)
+    g_cond_broadcast (demux->pldownloader->cond);
+
+  while (demux->download_task && (GST_TASK_STATE (demux->download_task) != GST_TASK_STOPPED)) {
+    int idx = 0;
+    GstHLSDemux2Stream *stream = NULL;
+
+    GST_INFO_OBJECT (demux, "Closing Download task...");
+
+    /* signal queue full conditions */
+    for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
+      stream = demux->streams[idx];
+
+      if (stream && GST_PAD_TASK(stream->pad)) {
+        gst_pad_push_event (stream->pad, gst_event_new_flush_start ());
+        g_cond_broadcast(stream->queue_full);
+        g_cond_broadcast(stream->queue_empty);
+      }
+    }
+
+    if (demux->pl_update_cond)
+      g_cond_broadcast (demux->pl_update_cond);
+
+    if (demux->fdownloader && demux->fdownloader->cond)
+      g_cond_broadcast (demux->fdownloader->cond);
+    if (demux->kdownloader && demux->kdownloader->cond)
+      g_cond_broadcast (demux->kdownloader->cond);
+    if (demux->pldownloader && demux->pldownloader->cond)
+      g_cond_broadcast (demux->pldownloader->cond);
+
+    GST_INFO_OBJECT (demux, "Waiting to acquire download lock");
+    g_static_rec_mutex_lock (&demux->download_lock);
+    g_static_rec_mutex_unlock (&demux->download_lock);
+
+    GST_INFO_OBJECT (demux, "Waiting download task JOIN");
+    gst_task_join (demux->download_task);
+    gst_object_unref (demux->download_task);
+    demux->download_task = NULL;
+
+    GST_INFO_OBJECT (demux, "Completed closing of download task...");
+
+    g_thread_join(demux->buffering_posting_thread);
+    GST_INFO_OBJECT (demux, "Completed closing of download monitor thread...");
+
+    if (demux->fdownloader && demux->fdownloader->pipe) {
+      GST_WARNING_OBJECT (demux, "Still fragment download exist");
+      gst_hlsdemux2_destroy_fragment_download (demux);
+    }
+    if (demux->pldownloader && demux->pldownloader->pipe) {
+      GST_WARNING_OBJECT (demux, "Still playlist download exist");
+      gst_hlsdemux2_destroy_playlist_download (demux);
+    }
+    if (demux->kdownloader && demux->kdownloader->pipe) {
+      GST_WARNING_OBJECT (demux, "Still key download exist");
+      gst_hlsdemux2_destroy_key_download (demux);
+    }
+  }
+
+  gst_hlsdemux2_stop_stream (demux);
+
+  GST_INFO_OBJECT (demux, "leaving...");
+}
+
+static void
+gst_hlsdemux2_stop_stream (GstHLSDemux2 *demux)
+{
+  int n = 0;
+  GstHLSDemux2Stream *stream = NULL;
+  gchar *pad_name = NULL;
+
+  GST_INFO_OBJECT (demux, "entering");
+
+  for (n = 0; n < HLSDEMUX2_STREAM_NUM; n++) {
+    stream = demux->streams[n];
+
+    if (stream && GST_PAD_TASK(stream->pad)) {
+      pad_name = gst_pad_get_name (stream->pad);
+      GST_INFO_OBJECT (stream->pad, "stopping pad task : %s", pad_name);
+      gst_pad_stop_task (stream->pad);
+      GST_INFO_OBJECT (stream->pad, "stopped pad task : %s", pad_name);
+      g_free(pad_name);
+      pad_name = NULL;
+    }
+  }
+
+  for (n = 0; n < HLSDEMUX2_STREAM_NUM; n++) {
+    if (demux->streams[n]) {
+      gst_hlsdemux2_stream_deinit(demux->streams[n], demux);
+      demux->streams[n] = NULL;
+    }
+  }
+  demux->active_stream_cnt = 0;
+  GST_INFO_OBJECT (demux, "leaving");
+}
+
+static void
+gst_hlsdemux2_stream_init (GstHLSDemux2 *demux, GstHLSDemux2Stream *stream, HLSDEMUX2_STREAM_TYPE stream_type, gchar *name, GstCaps *src_caps)
+{
+  stream->queue = g_queue_new ();
+  stream->queue_full = g_cond_new ();
+  stream->queue_empty = g_cond_new ();
+  stream->queue_lock = g_mutex_new ();
+  stream->parent = demux;
+  stream->type = stream_type;
+  stream->percent = 100;
+  stream->eos = FALSE;
+  stream->cached_duration = 0;
+  stream->lts = 0;
+  stream->dummy_data_thread = NULL;
+  stream->base_ts = GST_CLOCK_TIME_NONE;
+  stream->fts = GST_CLOCK_TIME_NONE;
+  stream->valid_fts_rcvd = FALSE;
+  stream->total_stream_time = 0;
+  stream->total_disc = 0;
+  stream->cdisc = 0;
+  stream->nts = GST_CLOCK_TIME_NONE;
+  stream->prev_nts = 0;
+  stream->downloader_queue = g_queue_new();
+  stream->need_newsegment = TRUE;
+  stream->newsegment = NULL;
+  stream->frame_duration = 0;
+
+  if (stream_type == HLSDEMUX2_STREAM_VIDEO) {
+    stream->pad = gst_pad_new_from_static_template (&hlsdemux2_videosrc_template, name);
+    GST_INFO_OBJECT (demux, "Its a Multi-variant stream..");
+    demux->stream_config = HLSDEMUX2_MULTI_VARIANT;
+  } else if (stream_type == HLSDEMUX2_STREAM_AUDIO) {
+    stream->pad = gst_pad_new_from_static_template (&hlsdemux2_audiosrc_template, name);
+  } else if (stream_type == HLSDEMUX2_STREAM_TEXT) {
+    stream->pad = gst_pad_new_from_static_template (&hlsdemux2_subpicture_template, name);
+  } else if (stream_type == HLSDEMUX2_STREAM_PRIVATE) {
+    stream->pad = gst_pad_new_from_static_template (&hlsdemux2_private_template, name);
+  }
+
+  GST_INFO_OBJECT (demux, "======>>>> created hlsdemux2 source pad : %s", name);
+
+  GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
+
+  gst_pad_use_fixed_caps (stream->pad);
+  gst_pad_set_event_function (stream->pad, gst_hlsdemux2_handle_src_event);
+  gst_pad_set_query_function (stream->pad, gst_hlsdemux2_src_query);
+  gst_pad_set_caps (stream->pad, src_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);
+
+  if (!gst_pad_is_linked (stream->pad)) {
+    GST_WARNING_OBJECT (stream->pad, "'%s' pad is not linked...", GST_OBJECT_NAME (stream->pad));
+    stream->is_linked = FALSE;
+    return;
+  }
+  stream->is_linked = TRUE;
+
+  if (!gst_pad_start_task (stream->pad, (GstTaskFunction) gst_hlsdemux2_push_loop, stream)) {
+    GST_ERROR_OBJECT (demux, "failed to create stream task...");
+    GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to create stream push loop"), (NULL));
+    return;
+  }
+
+}
+
+static void
+gst_hlsdemux2_stream_deinit (GstHLSDemux2Stream *stream, gpointer data)
+{
+  GstHLSDemux2 * demux = (GstHLSDemux2 *)data;
+  if (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->queue_lock) {
+      g_mutex_free (stream->queue_lock);
+      stream->queue_lock = NULL;
+    }
+    if (stream->queue_full) {
+      g_cond_free (stream->queue_full);
+      stream->queue_full = NULL;
+    }
+    if (stream->queue_empty) {
+      g_cond_free (stream->queue_empty);
+      stream->queue_empty= NULL;
+    }
+    g_free (stream);
+  }
+
+}
+
+static gboolean
+gst_hlsdemux2_set_location (GstHLSDemux2 * demux, const gchar * uri)
+{
+  if (demux->client)
+    gst_m3u8_client_free (demux->client);
+  demux->client = gst_m3u8_client_new (uri);
+  GST_INFO_OBJECT (demux, "Changed location: %s", uri);
+  return TRUE;
+}
+
+static gchar *
+gst_hlsdemux2_src_buf_to_utf8_playlist (GstBuffer * buf)
+{
+  gint size;
+  gchar *data;
+  gchar *playlist;
+
+  data = (gchar *) GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
+
+#if 0 /* giving error some times, so removing*/
+  if (!g_utf8_validate (data, size, NULL))
+    goto validate_error;
+#endif
+
+  /* alloc size + 1 to end with a null character */
+  playlist = g_malloc0 (size + 1);
+  if (!playlist) {
+    GST_ERROR ("failed to create memory...");
+    gst_buffer_unref (buf);
+    return NULL;
+  }
+
+  memcpy (playlist, data, size);
+  playlist[size] = '\0';
+
+  gst_buffer_unref (buf);
+  return playlist;
+#if 0
+validate_error:
+  gst_buffer_unref (buf);
+  GST_ERROR ("failed to validate playlist");
+  return NULL;
+#endif
+}
+
+static void
+gst_hlsdemux2_handle_private_pad (GstHLSDemux2 *demux, GstPad *srcpad)
+{
+  GstHLSDemux2PvtStream *pvt_stream = NULL;
+  gchar *sinkname = NULL;
+  GstPad *sinkpad = NULL;
+
+  pvt_stream = g_new0 (GstHLSDemux2PvtStream, 1);
+
+  demux->private_stream = pvt_stream;
+  pvt_stream->parent = demux;
+  pvt_stream->type = HLSDEMUX2_STREAM_PRIVATE;
+  pvt_stream->image_buffer = NULL;
+  pvt_stream->got_img_buffer = FALSE;
+  pvt_stream->video_buffer = NULL;
+  pvt_stream->id3_buffer   = NULL;
+  pvt_stream->convert_lock = g_mutex_new ();
+  pvt_stream->convert_cond = g_cond_new ();
+  pvt_stream->sink = NULL;
+  pvt_stream->img_load_lock = g_mutex_new ();
+  pvt_stream->img_load_cond = g_cond_new ();
+
+  /* create sink element */
+  sinkname = g_strdup_printf("%s-%s", GST_PAD_NAME(srcpad) , "sink");
+  pvt_stream->sink =  gst_element_factory_make ("appsink", NULL);
+  if (!pvt_stream->sink) {
+    GST_ERROR_OBJECT (demux, "failed to create sink element - %s", sinkname);
+    GST_ELEMENT_ERROR (demux, CORE, FAILED, ("failed to create element - %s", sinkname), (NULL));
+    g_free(sinkname);
+    sinkname = NULL;
+    return;
+  }
+
+  /* set sink element to PLAYING state */
+  gst_bin_add (GST_BIN (demux->fdownloader->pipe), pvt_stream->sink);
+  gst_element_set_state (pvt_stream->sink, GST_STATE_READY);
+  g_object_set (G_OBJECT (pvt_stream->sink), "sync", FALSE, "emit-signals", TRUE, NULL);
+
+  sinkpad = gst_element_get_pad(pvt_stream->sink, "sink");
+  if (!sinkpad) {
+    GST_ERROR_OBJECT (demux, "failed to get sinkpad from element  - %s", sinkname);
+    GST_ELEMENT_ERROR (demux, CORE, PAD, ("Count not get sink pad"), (NULL));
+    g_free(sinkname);
+    sinkname = NULL;
+    return;
+  }
+
+  if (gst_pad_link(srcpad, sinkpad) != GST_PAD_LINK_OK) {
+    GST_ERROR_OBJECT (demux, "failed to link sink bin elements");
+    GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("Could not link pads.."), (NULL));
+    gst_object_unref(sinkpad);
+  }
+
+  gst_element_set_state (pvt_stream->sink, GST_STATE_PLAYING);
+
+  g_signal_connect (pvt_stream->sink, "new-buffer",  G_CALLBACK (gst_hlsdemux2_private_sink_on_new_buffer), pvt_stream);
+  g_signal_connect (pvt_stream->sink, "eos",  G_CALLBACK (gst_hlsdemux2_private_sink_on_eos), pvt_stream);
+
+  gst_object_unref(sinkpad);
+
+  GST_INFO_OBJECT (demux, "successfully created private pad bin...");
+
+  g_free(sinkname);
+  sinkname = NULL;
+  return;
+}
+
+static void
+gst_hlsdemux2_private_sink_on_new_buffer (GstElement *appsink, void *user_data)
+{
+  GstHLSDemux2PvtStream *pvt_stream = (GstHLSDemux2PvtStream *)user_data;
+  GstHLSDemux2 *demux = pvt_stream->parent;
+  GstBuffer *inbuf = NULL;
+
+  inbuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
+  if (!inbuf) {
+    GST_ERROR_OBJECT (demux, "Input buffer not available....");
+    return;
+  }
+
+  GST_LOG_OBJECT (demux, "Image buffer received of size = %d", GST_BUFFER_SIZE (inbuf));
+  if(pvt_stream->id3_buffer==NULL)
+    pvt_stream->id3_buffer = gst_buffer_copy(inbuf);
+  else
+    pvt_stream->id3_buffer = gst_buffer_join (pvt_stream->id3_buffer, inbuf);
+  return;
+}
+
+static void
+gst_hlsdemux2_private_sink_on_eos (GstElement * appsink, void* user_data)
+{
+  GstHLSDemux2PvtStream *pvt_stream = (GstHLSDemux2PvtStream *)user_data;
+  GstHLSDemux2 *demux = pvt_stream->parent;
+  GstBuffer *image_buffer = NULL;
+  GstTagList *tag_list = gst_tag_list_from_id3v2_tag(pvt_stream->id3_buffer);
+
+  GST_INFO_OBJECT (demux, "Processing image buffer");
+
+  if(!gst_tag_list_get_buffer (tag_list, GST_TAG_IMAGE, &image_buffer)) {
+    GST_ERROR_OBJECT(demux, "Failed to obtain image data.");
+    return;
+  }
+
+  if(demux->stream_config == HLSDEMUX2_SINGLE_VARIANT) {
+    gchar *image_header = NULL;
+    GValue codec_type = G_VALUE_INIT;
+    GstMessage * tag_message = NULL;
+
+    /* check whether it is same as previous image */
+    if (demux->prev_image_buffer &&
+      (GST_BUFFER_SIZE(demux->prev_image_buffer) == GST_BUFFER_SIZE(image_buffer))) {
+      if (!memcmp (GST_BUFFER_DATA(demux->prev_image_buffer), GST_BUFFER_DATA(image_buffer), GST_BUFFER_SIZE(image_buffer))) {
+        GST_INFO_OBJECT (demux, "current & previous embedded images are same..no need to post image again");
+        gst_buffer_unref (image_buffer);
+        return;
+      }
+    }
+
+    if (demux->prev_image_buffer) {
+      gst_buffer_unref (demux->prev_image_buffer);
+    }
+    demux->prev_image_buffer = gst_buffer_copy(image_buffer);
+
+    image_header = g_strndup((gchar *) image_buffer->data, 8);
+
+    g_value_init (&codec_type, G_TYPE_STRING);
+
+    if((image_header[0] == 0xFF) && (image_header[1] == 0xD8)) {
+      GST_INFO_OBJECT(demux, "Found JPEG image header");
+      g_value_set_static_string (&codec_type, "image/jpeg");
+      gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
+    } else if (!g_strcmp0(image_header, "\211PNG\015\012\032\012")) {
+      GST_INFO_OBJECT(demux, "Found PNG image header");
+      g_value_set_static_string (&codec_type, "image/png");
+      gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
+    } else {
+      g_value_set_static_string (&codec_type, "image/unknown");
+      GST_INFO_OBJECT(demux, "Unknown image header");
+      gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
+    }
+
+    GST_INFO_OBJECT(demux, "Set value : %s", g_value_get_string (&codec_type));
+    g_value_unset(&codec_type);
+
+    tag_message = gst_message_new_tag (GST_OBJECT_CAST (demux), tag_list);
+    if(!gst_element_post_message (GST_ELEMENT_CAST (demux), tag_message)) {
+      GST_ERROR_OBJECT (demux, "failed to post image tag");
+      gst_buffer_unref (image_buffer);
+      g_free (image_header);
+      return;
+    }
+
+    GST_INFO_OBJECT (demux, "successfully posted image tag...");
+    gst_buffer_unref (image_buffer);
+    g_free (image_header);
+    return;
+  }
+
+  GST_INFO_OBJECT(demux, "image header : %d,%d", image_buffer->data[0],image_buffer->data[1]);
+
+  pvt_stream->image_buffer = gst_buffer_copy(image_buffer);
+  gst_buffer_unref (image_buffer);
+  pvt_stream->got_img_buffer = TRUE;
+
+  g_cond_signal (pvt_stream->img_load_cond);
+  demux->has_image_buffer = TRUE;
+
+}
+
+static gboolean
+hlsdemux2_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "hlsdemux2", GST_RANK_PRIMARY + 1, GST_TYPE_HLSDEMUX2) || FALSE)
+    return FALSE;
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "hlsdemux2",
+  "HLS demux - 2 plugin",
+  hlsdemux2_init,
+  VERSION,
+  "LGPL",
+  PACKAGE_NAME,
+  "http://www.samsung.com/")
+
diff --git a/hlsdemux2/src/gsthlsdemux2.h b/hlsdemux2/src/gsthlsdemux2.h
new file mode 100755 (executable)
index 0000000..15269a4
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * hlsdemux2
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, Naveen Cherukuri <naveen.ch@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * 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_HLSDEMUX2_H__
+#define __GST_HLSDEMUX2_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstadapter.h>
+#include <gst/app/gstappsrc.h>
+#include <gst/app/gstappsink.h>
+#include "m3u8.h"
+
+G_BEGIN_DECLS
+#define GST_TYPE_HLSDEMUX2  (gst_hlsdemux2_get_type())
+#define GST_HLSDEMUX2(obj)  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_HLSDEMUX2, GstHLSDemux2))
+#define GST_HLSDEMUX2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_HLSDEMUX2,GstHLSDemux2Class))
+#define GST_IS_HLSDEMUX2(obj)  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_HLSDEMUX2))
+#define GST_IS_HLSDEMUX2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_HLSDEMUX2))
+
+typedef struct _GstHLSDemux2 GstHLSDemux2;
+typedef struct _GstHLSDemux2Class GstHLSDemux2Class;
+typedef struct _GstHLSDemux2Stream GstHLSDemux2Stream;
+typedef struct _GstHLSDemux2PvtStream GstHLSDemux2PvtStream;
+
+#define GST_HLS_DEMUX_AES_BLOCK_SIZE 16
+
+#define ON_ERROR_REQUEST_AGAIN // Orange server giving soup errors. so, request for fail count times
+
+#define HLSDEMUX2_CHUNK_TIME_DURATION (0.5 * GST_SECOND)
+#define HLSDEMUX2_NUM_CHUNK_DOWNLOADS_FAST_SWITCH 4
+#define HLSDEMUX2_MAX_N_PAST_FRAG_DOWNLOADRATES 3
+
+#define HLSDEMUX2_FAST_CHECK_CRITICAL_TIME_FACTOR 1.2
+#define HLSDEMUX2_FAST_CHECK_WARNING_TIME_FACTOR 1
+
+#ifdef USING_AVG_PAST_DOWNLOADRATES
+#define HLSDEMUX2_MAX_N_PAST_DOWNLOADRATES 3
+#endif
+
+
+#define PLAYLIST_REFRESH_TIMEOUT (20 * GST_SECOND)
+
+#define HLSDEMUX2_OVERHEAD (1 * GST_SECOND)
+
+#define LATEST_AV_SYNC
+
+typedef enum
+{
+  HLSDEMUX2_STREAM_VIDEO = 0,
+  HLSDEMUX2_STREAM_AUDIO,
+  HLSDEMUX2_STREAM_TEXT,
+  HLSDEMUX2_STREAM_PRIVATE,
+  HLSDEMUX2_STREAM_NUM,
+}HLSDEMUX2_STREAM_TYPE;
+
+typedef enum
+{
+  HLSDEMUX2_DOWNWARD_RECOVERY = 0,
+  HLSDEMUX2_UPWARD_RECOVERY,
+  HLSDEMUX2_NO_RECOVERY,
+}HLSDEMUX2_RECOVERY_MODE;
+
+typedef enum
+{
+  HLSDEMUX2_MULTI_VARIANT = 0,
+  HLSDEMUX2_SINGLE_VARIANT
+}HLSDEMUX2_STREAM_CONFIGURATION;
+
+typedef struct
+{
+  GstBin *sinkbin;
+  GstElement *parser; /*only for .aac stream */
+  GstElement *queue;
+  GstElement *sink;
+}HLSDemux2SinkBin;
+
+typedef struct
+{
+  GstElement *pipe;
+  GstElement *urisrc;
+  GstElement *typefind;
+  GstElement *queue;
+  GstElement *demuxer;
+  GList *sinkbins;
+
+  guint64 content_size;
+  gboolean applied_fast_switch;
+
+  gchar *remaining_data;
+  guint remaining_size;
+
+  GMutex *lock;
+  GCond *cond;
+  gboolean is_encrypted;
+
+  gulong src_bprobe;
+  gboolean get_next_frag; /* on error like NOT_FOUND, request next fragment */
+
+  guint cur_stream_cnt;
+  gboolean first_buffer;
+  gboolean force_timestamps; /* useful in .aac files playback */
+  gboolean error_rcvd;
+  gboolean find_mediaseq;
+  GstClockTime seeked_pos;
+  GstClockTime cur_running_dur;
+
+  /* for fragment download rate calculation */
+  guint64 download_rate;
+  GstClockTime download_start_ts;
+  GstClockTime download_stop_ts;
+  guint64 src_downloaded_size;
+  guint64 queue_downloaded_size;
+  gint ndownloaded; /* number of fragments downloaded */
+  GArray *avg_chunk_drates; /* chunk download rates array */
+  GArray *avg_frag_drates; /* fragment download rates array */
+  guint64 chunk_downloaded_size;
+  GstClockTime chunk_start_ts;
+}HLSDemux2FragDownloader;
+
+/* playlist downloader */
+typedef struct
+{
+  GstElement *pipe;
+  GstBus *bus;
+  GstElement *urisrc;
+  GstElement *sink;
+  GMutex *lock;
+  GCond *cond;
+
+  GstBuffer *playlist;
+  HLSDEMUX2_RECOVERY_MODE recovery_mode;
+  GstClockTime download_start_ts;
+}HLSDemux2PLDownloader;
+
+/* Key downloader */
+typedef struct
+{
+  GstElement *pipe;
+  GstBus *bus;
+  GstElement *urisrc;
+  GstElement *sink;
+
+  GMutex *lock;
+  GCond *cond;
+
+  GstBuffer *key;
+  gchar *prev_key_uri;
+}HLSDemux2KeyDownloader;
+
+/**
+ * GstHLSDemux2:
+ *
+ * Opaque #GstHLSDemux2 data structure.
+ */
+struct _GstHLSDemux2
+{
+  GstElement parent;
+
+  GstPad *sinkpad;
+
+  /* M3U8 client */
+  GstM3U8Client *client;
+
+  gboolean is_live;
+
+  HLSDemux2FragDownloader *fdownloader; /* fragment downloader */
+  HLSDemux2PLDownloader *pldownloader; /* playlist downloader */
+  HLSDemux2KeyDownloader *kdownloader; /* key downloader */
+
+  /* properties */
+  gint blocksize;
+
+  /* master playlist got from upstream */
+  GstBuffer *playlist;
+
+  /* fragment download task */
+  GstTask *download_task;
+  GStaticRecMutex download_lock;
+
+  /* Playlist updates task for live session */
+  GStaticRecMutex updates_lock;
+  GTimeVal next_update;         /* Time of the next update */
+
+  /* playlist update condition */
+  GCond *pl_update_cond;
+  GMutex *pl_update_lock;
+
+  /* array of pointers to each stream's list */
+  GstHLSDemux2Stream *streams[HLSDEMUX2_STREAM_NUM];
+  gint active_stream_cnt;
+
+  gint percent; /* buffering percentage posting */
+  GMutex *buffering_lock;
+  gboolean is_buffering;
+  GThread *buffering_posting_thread;
+  GMutex *post_msg_lock;
+  GCond *post_msg_start;
+  GCond *post_msg_exit;
+
+  /* HTTP request cookies. */
+  gchar **lastCookie;
+  gchar **playlistCookie;
+  gchar **keyCookie;
+  gchar **fragCookie;
+  gchar *lastDomain;
+  gchar *playlistDomain;
+  gchar *keyDomain;
+  gchar *fragDomain;
+
+  gchar *user_agent;
+
+  /* Properties */
+  gfloat bitrate_switch_tol;    /* tolerance with respect to the fragment duration to switch the bitarate*/
+
+  gboolean cancelled;
+  gboolean end_of_playlist;
+
+  guint64 total_cache_duration;
+  guint64 target_duration;
+
+#ifdef ON_ERROR_REQUEST_AGAIN
+   /* requesting the same uron error */
+  gchar *playlist_uri;
+  gchar *frag_uri;  /* NOT supporting YET for fragment download errors*/
+  gchar *key_uri;
+#endif
+
+  int soup_request_fail_cnt;
+  /* can be removed [mainly for debugging & testing] */
+  gboolean force_lower_bitrate;
+
+  GstClockTime cfrag_dur;
+  gboolean error_posted;
+  gboolean flushing;
+  GstClockTime ns_start;
+  GstClockTime cur_audio_fts;
+
+  GstHLSDemux2PvtStream * private_stream;
+  gboolean has_image_buffer;
+  HLSDEMUX2_STREAM_CONFIGURATION stream_config;
+  GstBuffer *prev_image_buffer;
+  GstBuffer *prev_video_buffer;
+};
+
+struct _GstHLSDemux2Class
+{
+  GstElementClass parent_class;
+};
+
+GType gst_hlsdemux2_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_HLSDEMUX2_H__ */
diff --git a/hlsdemux2/src/m3u8.c b/hlsdemux2/src/m3u8.c
new file mode 100755 (executable)
index 0000000..f2a8621
--- /dev/null
@@ -0,0 +1,1246 @@
+/* GStreamer
+ * Copyright (C) 2010 Marc-Andre Lureau <marcandre.lureau@gmail.com>
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * m3u8.c:
+ *
+ * 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 <stdlib.h>
+#include <math.h>
+#include <errno.h>
+#include <glib.h>
+#include <string.h>
+#include "m3u8.h"
+
+static GstM3U8 *gst_m3u8_new (void);
+static void gst_m3u8_free (GstM3U8 * m3u8);
+static gboolean gst_m3u8_update (GstM3U8 * m3u8, gchar * data,
+    gboolean * updated);
+static GstM3U8MediaFile *
+gst_m3u8_media_file_new (gchar * uri, gchar * title, GstClockTime duration,
+    gchar *key_url, gchar *IV, guint sequence);
+static void gst_m3u8_media_file_free (GstM3U8MediaFile * self);
+static void gst_m3u8_key_free (GstM3U8Key * self);
+
+#define GST_CAT_DEFAULT hlsdemux2_m3u8_debug
+
+#define BITRATE_SWITCH_UPPER_THRESHOLD 0.3
+#define BITRATE_SWITCH_LOWER_THRESHOLD 0
+#define SWITCH_TRIGGER_POINT 1
+
+static GstM3U8 *
+gst_m3u8_new (void)
+{
+  GstM3U8 *m3u8;
+
+  m3u8 = g_new0 (GstM3U8, 1);
+  m3u8->last_data = NULL;
+  return m3u8;
+}
+
+static void
+gst_m3u8_set_uri (GstM3U8 * self, gchar * uri)
+{
+  g_return_if_fail (self != NULL);
+
+  if (self->uri)
+    g_free (self->uri);
+  self->uri = uri;
+}
+
+static void
+gst_m3u8_free (GstM3U8 * self)
+{
+  g_return_if_fail (self != NULL);
+
+  g_free (self->uri);
+  g_free (self->allowcache);
+  g_free (self->codecs);
+  //g_free (self->cipher_ctx);
+
+  g_list_foreach (self->files, (GFunc) gst_m3u8_media_file_free, NULL);
+  g_list_free (self->files);
+
+  g_free (self->last_data);
+  g_list_foreach (self->lists, (GFunc) gst_m3u8_free, NULL);
+  g_list_free (self->lists);
+
+  g_free (self);
+}
+
+static GstM3U8MediaFile *
+gst_m3u8_media_file_new (gchar * uri, gchar * title, GstClockTime duration,
+    gchar *key_url, gchar *IV, guint sequence)
+{
+  GstM3U8MediaFile *file;
+
+  file = g_new0 (GstM3U8MediaFile, 1);
+  file->uri = uri;
+  file->title = title;
+  file->duration = duration;
+  file->sequence = sequence;
+
+  GST_DEBUG ("Duration of the file = %"GST_TIME_FORMAT"\n", GST_TIME_ARGS(duration));
+
+  if (key_url != NULL)
+    file->key_url = g_strdup (key_url);
+  else
+    file->key_url = NULL;
+
+  file->iv = IV;
+
+  return file;
+}
+
+static void
+gst_m3u8_media_file_free (GstM3U8MediaFile * self)
+{
+  g_return_if_fail (self != NULL);
+
+  if (self->key_url) {
+    g_free (self->key_url);
+    self->key_url = NULL;
+  }
+  if (self->iv) {
+    g_free (self->iv);
+    self->iv = NULL;
+  }
+  if (self->title) {
+    g_free (self->title);
+    self->title = NULL;
+  }
+  if (self->uri){
+    g_free (self->uri);
+    self->uri = NULL;
+  }
+  g_free (self);
+}
+
+static gchar *
+gst_m3u8_getIV_from_mediasequence (GstM3U8 *self)
+{
+  gchar *IV = NULL;
+
+  IV = g_malloc0 (16);
+  if (!IV) {
+    GST_ERROR ("Failed to allocate memory...");
+    return NULL;
+  }
+
+  if (self->mediasequence > INT_MAX) {
+    GST_ERROR ("media sequnece is greater than INT_MAX...yet to handle");
+  }
+
+  IV [15] = (gchar)(self->mediasequence);
+  IV [14] = (gchar)(self->mediasequence >> 8);
+  IV [13] = (gchar)(self->mediasequence >> 16);
+  IV [12] = (gchar)(self->mediasequence >> 24);
+  return IV;
+}
+
+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)) {
+    GST_WARNING ("%s", g_strerror (errno));
+    return FALSE;
+  }
+
+  if (endptr)
+    *endptr = end;
+
+  return end != ptr;
+}
+
+static gboolean
+double_from_string (gchar * ptr, gchar ** endptr, gdouble * val)
+{
+  gchar *end;
+  gdouble ret;
+
+  g_return_val_if_fail (ptr != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  errno = 0;
+  ret = g_strtod (ptr, &end);
+  if ((errno == ERANGE && (ret == HUGE_VAL || ret == -HUGE_VAL))
+      || (errno != 0 && ret == 0)) {
+    GST_WARNING ("%s", g_strerror (errno));
+    return FALSE;
+  }
+
+  if (!isfinite (ret)) {
+    GST_WARNING ("%s", g_strerror (ERANGE));
+    return FALSE;
+  }
+
+  if (endptr)
+    *endptr = end;
+
+  *val = (gdouble) ret;
+
+  return end != ptr;
+}
+
+static gboolean
+iv_from_string (gchar * ptr, gchar ** endptr, guint8 * val)
+{
+  guint8 idx;
+  guint8 hex;
+
+  g_return_val_if_fail (ptr != NULL, FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  if (*ptr == '0' && (*(ptr + 1) == 'x' || *(ptr + 1) == 'X')) {
+    ptr = ptr + 2;  /* skip 0x or 0X */
+  }
+
+  for (idx = 0; idx < GST_M3U8_IV_LEN; idx++) {
+    hex = *ptr++ - '0';
+    if (hex >= 16)
+      return FALSE;
+    *(val + idx) = hex * 16;
+    hex = *ptr++ - '0';
+    if (hex >= 16)
+      return FALSE;
+    *(val + idx) += hex;
+  }
+
+  if (endptr)
+    *endptr = ptr;
+
+  return TRUE;
+}
+
+static gboolean
+iv_from_uint (guint uint, guint8 * val)
+{
+  guint8 idx;
+
+  g_return_val_if_fail (val != NULL, FALSE);
+
+  val = val + GST_M3U8_IV_LEN - 1;
+  for (idx = 0; idx < sizeof(guint); idx++) {
+    *val-- = (guint8)uint;
+    uint = uint >> 8;
+  }
+  return TRUE;
+}
+
+static gboolean
+make_valid_uri (gchar *prefix, gchar *suffix, gchar **uri)
+{
+  gchar *slash;
+
+  if (!prefix) {
+    GST_WARNING ("uri prefix not set, can't build a valid uri");
+    return FALSE;
+  }
+  slash = g_utf8_strrchr (prefix, -1, '/');
+  if (!slash) {
+    GST_WARNING ("Can't build a valid uri");
+    return FALSE;
+  }
+
+  *slash = '\0';
+  *uri = g_strdup_printf ("%s/%s", prefix, suffix);
+  *slash = '/';
+
+  return TRUE;
+}
+
+static gboolean
+parse_attributes (gchar ** ptr, gchar ** a, gchar ** v)
+{
+  gchar *end, *p;
+
+  g_return_val_if_fail (ptr != NULL, FALSE);
+  g_return_val_if_fail (*ptr != NULL, FALSE);
+  g_return_val_if_fail (a != NULL, FALSE);
+  g_return_val_if_fail (v != NULL, FALSE);
+
+  /* [attribute=value,]* */
+
+  *a = *ptr;
+  end = p = g_utf8_strchr (*ptr, -1, ',');
+  if (end) {
+    do {
+      end = g_utf8_next_char (end);
+    } while (end && *end == ' ');
+    *p = '\0';
+  }
+
+  *v = p = g_utf8_strchr (*ptr, -1, '=');
+  if (*v) {
+    *v = g_utf8_next_char (*v);
+    *p = '\0';
+  } else {
+    GST_WARNING ("missing = after attribute");
+    return FALSE;
+  }
+
+  *ptr = end;
+  return TRUE;
+}
+
+static gint
+_m3u8_compare_uri (GstM3U8 * a, gchar * uri)
+{
+  g_return_val_if_fail (a != NULL, 0);
+  g_return_val_if_fail (uri != NULL, 0);
+
+  return g_strcmp0 (a->uri, uri);
+}
+
+static gint
+gst_m3u8_compare_playlist_by_bitrate (gconstpointer a, gconstpointer b)
+{
+  return ((GstM3U8 *) (a))->bandwidth - ((GstM3U8 *) (b))->bandwidth;
+}
+
+/*
+ * @data: a m3u8 playlist text data, taking ownership
+ */
+static gboolean
+gst_m3u8_update (GstM3U8 * self, gchar *data, gboolean * updated)
+{
+  gint val;
+  GstClockTime duration = 0;
+  gchar *title, *end;
+//  gboolean discontinuity;
+  GstM3U8 *list;
+  gchar  *key_url = NULL;
+  gchar *IV = NULL;
+  gchar *actual_data = NULL;
+
+  g_return_val_if_fail (self != NULL, FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (updated != NULL, FALSE);
+
+  *updated = TRUE;
+
+  /* check if the data changed since last update */
+  if (self->last_data && g_str_equal (self->last_data, data)) {
+    GST_DEBUG ("Playlist is the same as previous one");
+    *updated = FALSE;
+    g_free (data);
+    return TRUE;
+  }
+
+  if (!g_str_has_prefix (data, "#EXTM3U")) {
+    GST_WARNING ("Data doesn't start with #EXTM3U");
+    *updated = FALSE;
+    g_free (data);
+    return FALSE;
+  }
+
+  if (self->last_data)
+    g_free (self->last_data);
+
+  self->last_data = g_strdup(data);
+
+  actual_data = data;
+
+  if (self->files) {
+    g_list_foreach (self->files, (GFunc) gst_m3u8_media_file_free, NULL);
+    g_list_free (self->files);
+    self->files = NULL;
+  }
+
+  list = NULL;
+  duration = 0;
+  title = NULL;
+  data += 7;
+
+  while (TRUE) {
+
+    end = g_utf8_strchr (data, -1, '\n');
+    if (end)
+      *end = '\0';
+
+    if (data[0] != '#') {
+      gchar *r;
+      gchar *uri = NULL;
+
+      if (duration <= 0 && list == NULL) {
+        GST_LOG ("%s: got line without EXTINF or EXTSTREAMINF, dropping", data);
+        goto next_line;
+      }
+
+      if (!gst_uri_is_valid (data)) {
+        if (!make_valid_uri(self->uri, data, &uri))
+          goto next_line;
+      } else {
+        uri = g_strdup (data);
+      }
+
+      r = g_utf8_strchr (uri, -1, '\r');
+      if (r)
+        *r = '\0';
+
+      if (list != NULL) {
+        if (g_list_find_custom (self->lists, uri, (GCompareFunc) _m3u8_compare_uri)) {
+          GST_DEBUG ("Already have a list with this URI");
+          gst_m3u8_free (list);
+          g_free (uri);
+        } else {
+          gst_m3u8_set_uri (list, uri);
+          self->lists = g_list_append (self->lists, list);
+        }
+        list = NULL;
+      } else {
+        GstM3U8MediaFile *file;
+        gchar *send_IV = NULL;
+
+        if (key_url) {
+          GST_DEBUG ("AES-128 key url = %s", key_url);
+          if (NULL == IV) {
+            /* IV is not present in EXT-X-KEY tag. Prepare IV based on mediasequence */
+            GST_DEBUG ("IV is not in EXT-X-KEY tag... generating from media_seq_num = %d", self->mediasequence);
+            send_IV = gst_m3u8_getIV_from_mediasequence (self);
+          } else {
+            int i=0;
+            send_IV = g_malloc0(16);
+            for(i=0;i<16;i++){
+              send_IV[i]=IV[i];
+            }
+          }
+        }
+
+        file =
+            gst_m3u8_media_file_new (uri, title, duration, key_url, send_IV,
+            self->mediasequence++);
+        duration = 0;
+        title = NULL;
+        send_IV = NULL;
+
+        self->files = g_list_append (self->files, file);
+        GST_DEBUG ("------------>>>>>>appending uri = %s and key = %s\n", file->uri, file->key_url);
+      }
+    } else if (g_str_has_prefix (data, "#EXT-X-ENDLIST")) {
+      GST_DEBUG ("*************** End list is present ****************");
+      self->endlist = TRUE;
+    } else if (g_str_has_prefix (data, "#EXT-X-VERSION:")) {
+      if (int_from_string (data + 15, &data, &val, 10))
+        self->version = val;
+    } else if (g_str_has_prefix (data, "#EXT-X-STREAM-INF:")) {
+      gchar *v, *a;
+
+      if (list != NULL) {
+        GST_WARNING ("Found a list without a uri..., dropping");
+        gst_m3u8_free (list);
+      }
+
+      list = gst_m3u8_new ();
+      data = data + 18;
+      while (data && parse_attributes (&data, &a, &v)) {
+        if (g_str_equal (a, "BANDWIDTH")) {
+          if (!int_from_string (v, NULL, &list->bandwidth, 10))
+            GST_WARNING ("Error while reading BANDWIDTH");
+        } else if (g_str_equal (a, "PROGRAM-ID")) {
+          if (!int_from_string (v, NULL, &list->program_id, 10))
+            GST_WARNING ("Error while reading PROGRAM-ID");
+        } else if (g_str_equal (a, "CODECS")) {
+          g_free (list->codecs);
+          list->codecs = g_strdup (v);
+        } else if (g_str_equal (a, "RESOLUTION")) {
+          if (!int_from_string (v, &v, &list->width, 10))
+            GST_WARNING ("Error while reading RESOLUTION width");
+          if (!v || *v != '=') {
+            GST_WARNING ("Missing height");
+          } else {
+            v = g_utf8_next_char (v);
+            if (!int_from_string (v, NULL, &list->height, 10))
+              GST_WARNING ("Error while reading RESOLUTION height");
+          }
+        }
+      }
+    } else if (g_str_has_prefix (data, "#EXT-X-TARGETDURATION:")) {
+      if (int_from_string (data + 22, &data, &val, 10))
+        self->targetduration = val * GST_SECOND;
+    } else if (g_str_has_prefix (data, "#EXT-X-MEDIA-SEQUENCE:")) {
+      if (int_from_string (data + 22, &data, &val, 10))
+        self->mediasequence = val;
+    } else if (g_str_has_prefix (data, "#EXT-X-DISCONTINUITY")) {
+      /* discontinuity = TRUE; */
+    } else if (g_str_has_prefix (data, "#EXT-X-PROGRAM-DATE-TIME:")) {
+      /* <YYYY-MM-DDThh:mm:ssZ> */
+      GST_DEBUG ("FIXME parse date");
+    } else if (g_str_has_prefix (data, "#EXT-X-ALLOW-CACHE:")) {
+      g_free (self->allowcache);
+      self->allowcache = g_strdup (data + 19);
+    } else if (g_str_has_prefix (data, "#EXTINF:")) {
+      gdouble fval;
+      if (!double_from_string (data + 8, &data, &fval)) {
+        GST_WARNING ("Can't read EXTINF duration");
+        goto next_line;
+      }
+      duration = fval * (gdouble) GST_SECOND;
+      if (duration > self->targetduration)
+        GST_WARNING ("EXTINF duration > TARGETDURATION");
+      if (!data || *data != ',')
+        goto next_line;
+      data = g_utf8_next_char (data);
+      if (data != end) {
+        g_free (title);
+        title = g_strdup (data);
+      }
+    } else if (g_str_has_prefix (data, "#EXT-X-KEY:"))  {
+      gchar *val, *attr;
+      GST_DEBUG ("Found EXT-X-KEY tag...");
+
+      /* handling encrypted content */
+      data = data + 11; /* skipping "#EXT-X-KEY:" tag */
+
+      while (data && parse_attributes (&data, &attr, &val)) {
+        if (g_str_equal (attr, "METHOD")) {
+          if (g_str_equal (val, "NONE")) {
+            GST_LOG ("Non encrypted file...and skipping current line and going to next line\n");
+            goto next_line;
+          } else if (g_str_equal (val, "AES-128")) {
+            /* media files are encrypted */
+            GST_LOG ("media files are encrypted with AES-128\n");
+            // TODO: indicate in flag whether encrypted files or not
+          }
+        } else if (g_str_equal (attr, "URI")) {
+          gchar *end_dq = NULL;
+
+          if (!val){
+            GST_ERROR ("val is NULL");
+            break;
+          }
+
+          val = val + 1; /* eliminating first double quote in url */
+          if (!val) {
+            GST_ERROR ("val is NULL");
+            break;
+          }
+
+          end_dq = g_utf8_strrchr (val, -1, '"');
+          if (!end_dq) {
+            GST_ERROR ("end_dq is NULL");
+            break;
+          }
+
+          *end_dq = '\0';
+          GST_DEBUG ("Key URI = %s\n", val);
+
+          if (!gst_uri_is_valid (val)) {
+            gchar *slash;
+            if (!self->uri) {
+              GST_WARNING ("uri not set, can't build a valid uri");
+              goto next_line;
+            }
+            slash = g_utf8_strrchr (self->uri, -1, '/');
+            if (!slash) {
+              GST_WARNING ("Can't build a valid uri");
+              goto next_line;
+            }
+            *slash = '\0';
+            key_url = g_strdup_printf ("%s/%s", self->uri, val);
+            *slash = '/';
+          } else {
+            key_url= g_strdup (val);
+          }
+        } else if (g_str_equal (attr, "IV")) {
+          gint iv_len = 0;
+          gchar tmp_byte[3];
+          gint tmp_val = 0;
+          gint idx = 0;
+          gchar *car = NULL;
+
+          if (IV) {
+            g_free (IV);
+            IV = NULL;
+          }
+
+          IV = g_malloc0 (16);
+          if (NULL == IV) {
+            GST_ERROR ("Failed to allocate memory...\n");
+            goto error;
+          }
+
+          /* eliminating 0x/0X prefix */
+          val = val + 2;
+          car = g_utf8_strchr (val, -1, '\r');
+          if (car)
+            *car = '\0';
+
+          iv_len = g_utf8_strlen(val, -1);
+          if (iv_len < 1 || iv_len >32) {
+            GST_ERROR ("Wrong IV and iv_len = %d", iv_len);
+            goto error;
+          }
+
+          val+=iv_len;
+          idx = 15;
+          while (iv_len > 0) {
+            // TODO: val need to incremented I feel.. check again
+            val-=(iv_len==1)?1:2;
+            g_utf8_strncpy(tmp_byte, val, (iv_len==1)?1:2);
+            tmp_byte[2] = '\0';
+            tmp_val = 0;
+            if (!int_from_string (tmp_byte, NULL, &tmp_val, 16))
+              GST_WARNING ("Error while reading PROGRAM-ID");
+            IV[idx] = tmp_val;
+            idx--;
+            iv_len = iv_len - 2;
+          }
+        }
+      }
+    } else {
+      GST_LOG ("Ignored line: %s", data);
+    }
+
+  next_line:
+    if (!end)
+      break;
+    data = g_utf8_next_char (end);      /* skip \n */
+  }
+
+  /* redorder playlists by bitrate */
+  if (self->lists) {
+    gchar *top_variant_uri = NULL;
+
+    if (!self->current_variant)
+      top_variant_uri = GST_M3U8 (self->lists->data)->uri;
+    else
+      top_variant_uri = GST_M3U8 (self->current_variant->data)->uri;
+
+    self->lists =
+        g_list_sort (self->lists,
+        (GCompareFunc) gst_m3u8_compare_playlist_by_bitrate);
+
+    self->current_variant = g_list_find_custom (self->lists, top_variant_uri,
+        (GCompareFunc) _m3u8_compare_uri);
+  }
+
+  g_free (actual_data);
+  actual_data = NULL;
+  g_free (key_url);
+  key_url = NULL;
+  g_free (title);
+  title = NULL;
+  return TRUE;
+
+error:
+  g_free (actual_data);
+  actual_data = NULL;
+  g_free (key_url);
+  key_url = NULL;
+  g_free (title);
+  title = NULL;
+  return FALSE;
+}
+
+
+GstM3U8Client *
+gst_m3u8_client_new (const gchar * uri)
+{
+  GstM3U8Client *client;
+
+  g_return_val_if_fail (uri != NULL, NULL);
+
+  client = g_new0 (GstM3U8Client, 1);
+  client->main = gst_m3u8_new ();
+  client->current = NULL;
+  client->sequence = -1;
+  client->update_failed_count = 0;
+  client->lock = g_mutex_new ();
+  gst_m3u8_set_uri (client->main, g_strdup (uri));
+
+  return client;
+}
+
+void
+gst_m3u8_client_free (GstM3U8Client * self)
+{
+  g_return_if_fail (self != NULL);
+
+  gst_m3u8_free (self->main);
+  g_mutex_free (self->lock);
+  g_free (self);
+}
+
+void
+gst_m3u8_client_set_current (GstM3U8Client * self, GstM3U8 * m3u8)
+{
+  g_return_if_fail (self != NULL);
+
+  GST_M3U8_CLIENT_LOCK (self);
+  if (m3u8 != self->current) {
+    self->current = m3u8;
+    self->update_failed_count = 0;
+  }
+  GST_M3U8_CLIENT_UNLOCK (self);
+}
+
+static guint
+_get_start_sequence (GstM3U8Client * client)
+{
+  GList *l;
+  GstClockTime duration_limit, duration_count = 0;
+  guint sequence = -1;
+
+  if (client->current->endlist) {
+    l = g_list_first (client->current->files);
+    sequence = GST_M3U8_MEDIA_FILE (l->data)->sequence;
+  } else {
+    duration_limit = client->current->targetduration * 3;
+    for (l = g_list_last (client->current->files); l; l = l->prev) {
+      duration_count += GST_M3U8_MEDIA_FILE (l->data)->duration;
+      sequence = GST_M3U8_MEDIA_FILE (l->data)->sequence;
+      if (duration_count >= duration_limit) {
+        break;
+      }
+    }
+  }
+  return sequence;
+}
+
+gboolean
+gst_m3u8_client_update (GstM3U8Client * self, gchar * data)
+{
+  GstM3U8 *m3u8;
+  gboolean updated = FALSE;
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (self != NULL, FALSE);
+
+  GST_M3U8_CLIENT_LOCK (self);
+  m3u8 = self->current ? self->current : self->main;
+
+  if (!gst_m3u8_update (m3u8, data, &updated))
+    goto out;
+
+  if (!updated) {
+    self->update_failed_count++;
+    goto out;
+  }
+
+  /* select the first playlist, for now */
+  if (!self->current) {
+    if (self->main->lists) {
+      self->current = self->main->current_variant->data;
+    } else {
+      self->current = self->main;
+    }
+  }
+
+  if (m3u8->files && self->sequence == -1) {
+#if 0
+    self->sequence = GST_M3U8_MEDIA_FILE (g_list_first (m3u8->files)->data)->sequence;
+#else
+    /* (spec : 6.3.3) In live case, the client SHOULD NOT choose a segment
+        which starts less than three target durations from the end of the Playlist file */
+    self->sequence = _get_start_sequence (self);
+#endif
+    GST_DEBUG ("Setting first sequence at %d", self->sequence);
+  }
+
+  ret = TRUE;
+out:
+  GST_M3U8_CLIENT_UNLOCK (self);
+  return ret;
+}
+
+static gboolean
+_find_next (GstM3U8MediaFile * file, GstM3U8Client * client)
+{
+  GST_DEBUG ("Found fragment %d", file->sequence);
+  if (file->sequence >= client->sequence)
+    return FALSE;
+  return TRUE;
+}
+
+static gboolean
+_find_key (GstM3U8Key * key, GstM3U8Client * client)
+{
+  if (key->sequence <= client->sequence)
+    return FALSE;
+  return TRUE;
+}
+
+void
+gst_m3u8_client_get_current_position (GstM3U8Client * client,
+    GstClockTime * timestamp)
+{
+  GList *l;
+  GList *walk;
+
+  l = g_list_find_custom (client->current->files, client,
+      (GCompareFunc) _find_next);
+
+  *timestamp = 0;
+  for (walk = client->current->files; walk; walk = walk->next) {
+    if (walk == l)
+      break;
+    *timestamp += GST_M3U8_MEDIA_FILE (walk->data)->duration;
+  }
+}
+
+gboolean
+gst_m3u8_client_get_next_fragment (GstM3U8Client * client, GstClockTime cur_running_time,
+    gboolean * discontinuity, const gchar ** uri, GstClockTime * duration,
+    GstClockTime * timestamp, gchar **key_uri, gchar **iv)
+{
+  GList *l;
+  GstM3U8MediaFile *file;
+
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (client->current != NULL, FALSE);
+  g_return_val_if_fail (discontinuity != NULL, FALSE);
+
+  GST_M3U8_CLIENT_LOCK (client);
+
+  GST_DEBUG ("Looking for fragment %d", client->sequence);
+
+  if (client->main && client->main->lists && client->current->endlist) {
+    GList *walk = NULL;
+    GstClockTime current_pos, target_pos;
+    gint current_sequence;
+    gboolean found_sequence = FALSE;
+
+    /* VOD playlist, so find mediasequence from time */
+    // TODO: need to handle when live converts to VOD by putting END_LIST tag
+
+    file = GST_M3U8_MEDIA_FILE (client->current->files->data);
+    current_sequence = file->sequence;
+    current_pos = 0 ;
+    target_pos = cur_running_time;
+
+    for (walk = client->current->files; walk; walk = walk->next) {
+      file = walk->data;
+
+      current_sequence = file->sequence;
+      if (current_pos <= target_pos &&
+        target_pos < current_pos + file->duration) {
+        found_sequence = TRUE;
+        break;
+      }
+      current_pos += file->duration;
+    }
+
+    if (found_sequence) {
+      GST_ERROR ("changing client sequence from %d -> %d", client->sequence, current_sequence);
+      client->sequence = current_sequence;
+    } else {
+      GST_WARNING ("max file_seq = %d and client_seq = %d", current_sequence, client->sequence);
+      GST_M3U8_CLIENT_UNLOCK (client);
+      return FALSE;
+    }
+  }
+
+  l = g_list_find_custom (client->current->files, client, (GCompareFunc) _find_next);
+  if (l == NULL) {
+    GST_M3U8_CLIENT_UNLOCK (client);
+    return FALSE;
+  }
+
+  gst_m3u8_client_get_current_position (client, timestamp);
+
+  file = GST_M3U8_MEDIA_FILE (l->data);
+
+  if (file->key_url)
+    *key_uri = g_strdup (file->key_url);
+
+  if (file->iv) {
+    *iv = g_malloc0 (GST_M3U8_IV_LEN);
+    //*iv = file->iv;
+    memcpy (*iv, file->iv, GST_M3U8_IV_LEN);
+  }
+
+  *discontinuity = client->sequence != file->sequence;
+  client->sequence = file->sequence + 1;
+
+  if (file->uri)
+    *uri = g_strdup (file->uri);
+
+  *duration = file->duration;
+
+  GST_M3U8_CLIENT_UNLOCK (client);
+  return TRUE;
+}
+
+void gst_m3u8_client_decrement_sequence (GstM3U8Client * client)
+{
+  GST_M3U8_CLIENT_LOCK (client);
+  client->sequence = client->sequence - 1;
+  GST_M3U8_CLIENT_UNLOCK (client);
+}
+
+static void
+_sum_duration (GstM3U8MediaFile * self, GstClockTime * duration)
+{
+  *duration += self->duration;
+}
+
+GstClockTime
+gst_m3u8_client_get_duration (GstM3U8Client * client)
+{
+  GstClockTime duration = 0;
+
+  g_return_val_if_fail (client != NULL, GST_CLOCK_TIME_NONE);
+
+  GST_M3U8_CLIENT_LOCK (client);
+  /* We can only get the duration for on-demand streams */
+  if (!client->current->endlist) {
+    GST_M3U8_CLIENT_UNLOCK (client);
+    return GST_CLOCK_TIME_NONE;
+  }
+
+  g_list_foreach (client->current->files, (GFunc) _sum_duration, &duration);
+  GST_M3U8_CLIENT_UNLOCK (client);
+  return duration;
+}
+
+GstClockTime
+gst_m3u8_client_get_target_duration (GstM3U8Client * client)
+{
+  GstClockTime duration = 0;
+
+  g_return_val_if_fail (client != NULL, GST_CLOCK_TIME_NONE);
+
+  GST_M3U8_CLIENT_LOCK (client);
+  duration = client->current->targetduration;
+  GST_M3U8_CLIENT_UNLOCK (client);
+  return duration;
+}
+
+/* used for LIVE case only, to update playlist file */
+GstClockTime
+gst_m3u8_client_get_last_fragment_duration (GstM3U8Client * client)
+{
+  GstClockTime duration = 0;
+  GstM3U8MediaFile *last_file = NULL;
+  GList *last_list = NULL;
+
+  g_return_val_if_fail (client != NULL, GST_CLOCK_TIME_NONE);
+
+  GST_M3U8_CLIENT_LOCK (client);
+
+  if (!client->current) {
+    GST_ERROR ("current variant is NULL.. return CLOCK_NONE");
+    GST_M3U8_CLIENT_UNLOCK (client);
+    return GST_CLOCK_TIME_NONE;
+  }
+
+  if (!client->current->files) {
+    GST_WARNING ("Due to playlist updation problem.. did not update the playlist");
+    GST_M3U8_CLIENT_UNLOCK (client);
+    return 0; /* update playlist immediately */
+  }
+
+  last_list = g_list_last (client->current->files);
+
+  if (!last_list) {
+    GST_WARNING ("list does not have last object... return target_duration");
+    GST_M3U8_CLIENT_UNLOCK (client);
+    return client->current->targetduration;
+  }
+
+  last_file = (GstM3U8MediaFile *)(last_list->data);
+  if(last_file)
+    duration = last_file->duration;
+  else
+    duration=client->current->targetduration;
+
+  GST_DEBUG ("Last file duration = %"GST_TIME_FORMAT"\n", GST_TIME_ARGS(duration));
+  GST_M3U8_CLIENT_UNLOCK (client);
+  return duration;
+}
+
+const gchar *
+gst_m3u8_client_get_uri (GstM3U8Client * client)
+{
+  const gchar *uri;
+
+  g_return_val_if_fail (client != NULL, NULL);
+
+  GST_M3U8_CLIENT_LOCK (client);
+  uri = client->main->uri;
+  GST_M3U8_CLIENT_UNLOCK (client);
+  return uri;
+}
+
+const gchar *
+gst_m3u8_client_get_current_uri (GstM3U8Client * client)
+{
+  const gchar *uri;
+
+  g_return_val_if_fail (client != NULL, NULL);
+
+  GST_M3U8_CLIENT_LOCK (client);
+  uri = client->current->uri;
+  GST_M3U8_CLIENT_UNLOCK (client);
+  return uri;
+}
+
+gint
+gst_m3u8_client_get_current_bandwidth (GstM3U8Client * client)
+{
+  gint bandwidth;
+
+  g_return_val_if_fail (client != NULL, -1);
+
+  GST_M3U8_CLIENT_LOCK (client);
+  bandwidth = client->current->bandwidth;
+  GST_M3U8_CLIENT_UNLOCK (client);
+  return bandwidth;
+}
+
+gboolean
+gst_m3u8_client_has_variant_playlist (GstM3U8Client * client)
+{
+  gboolean ret;
+
+  g_return_val_if_fail (client != NULL, FALSE);
+
+  GST_M3U8_CLIENT_LOCK (client);
+  ret = (client->main->lists != NULL);
+  GST_M3U8_CLIENT_UNLOCK (client);
+  return ret;
+}
+
+gboolean
+gst_m3u8_client_is_live (GstM3U8Client * client)
+{
+  gboolean ret;
+
+  g_return_val_if_fail (client != NULL, FALSE);
+
+  GST_M3U8_CLIENT_LOCK (client);
+  if (!client->current || client->current->endlist)
+    ret = FALSE;
+  else
+    ret = TRUE;
+  GST_M3U8_CLIENT_UNLOCK (client);
+  return ret;
+}
+
+GList *
+gst_m3u8_client_get_next_higher_bw_playlist (GstM3U8Client * client)
+{
+  GList *current_variant;
+
+  g_return_val_if_fail (client != NULL, FALSE);
+
+  GST_M3U8_CLIENT_LOCK (client);
+  current_variant = g_list_next (client->main->current_variant);
+  if (!current_variant) {
+    GST_WARNING ("no next variant available...");
+    GST_M3U8_CLIENT_UNLOCK (client);
+    return NULL;
+  }
+
+  GST_DEBUG ("next variant = %p and uri = %s", current_variant, GST_M3U8(current_variant->data)->uri);
+  GST_M3U8_CLIENT_UNLOCK (client);
+  return current_variant;
+
+}
+
+GList *
+gst_m3u8_client_get_next_lower_bw_playlist (GstM3U8Client * client)
+{
+  GList *current_variant;
+
+  g_return_val_if_fail (client != NULL, FALSE);
+
+  GST_M3U8_CLIENT_LOCK (client);
+  current_variant = g_list_previous (client->main->current_variant);
+  if (!current_variant) {
+    GST_WARNING ("no previous variant available...");
+    GST_M3U8_CLIENT_UNLOCK (client);
+    return NULL;
+  }
+
+  GST_DEBUG ("previous variant = %p and uri = %s", current_variant, GST_M3U8(current_variant->data)->uri);
+  GST_M3U8_CLIENT_UNLOCK (client);
+  return current_variant;
+}
+
+
+#ifndef SWITCH_TRIGGER_POINT
+GList *
+gst_m3u8_client_get_playlist_for_bitrate (GstM3U8Client * client, guint bitrate)
+{
+  GList *list, *current_variant;
+
+  GST_M3U8_CLIENT_LOCK (client);
+  current_variant = client->main->current_variant;
+
+  /*  Go to the highest possible bandwidth allowed */
+  while (GST_M3U8 (current_variant->data)->bandwidth < bitrate) {
+    list = g_list_next (current_variant);
+    if (!list)
+      break;
+    current_variant = list;
+  }
+
+  while (GST_M3U8 (current_variant->data)->bandwidth > bitrate) {
+    list = g_list_previous (current_variant);
+    if (!list)
+      break;
+    current_variant = list;
+  }
+  GST_M3U8_CLIENT_UNLOCK (client);
+
+  return current_variant;
+}
+#else
+GList *
+gst_m3u8_client_get_playlist_for_bitrate (GstM3U8Client * client, guint bitrate)
+{
+  GList *next_variant = NULL;
+  GList *current_variant = NULL;
+  guint current_bandwidth = 0;
+
+  GST_M3U8_CLIENT_LOCK (client);
+  current_variant = client->main->current_variant;
+  current_bandwidth = GST_M3U8 (current_variant->data)->bandwidth;
+
+  if ((current_bandwidth + BITRATE_SWITCH_UPPER_THRESHOLD * current_bandwidth) < bitrate) {
+    GST_DEBUG ("Switch to upper band...\n");
+
+    if (!g_list_next (current_variant)) {
+      GST_DEBUG ("no next upper fragment...\n");
+      GST_M3U8_CLIENT_UNLOCK (client);
+      return current_variant;
+    } else {
+      GST_DEBUG (">>>>> UP : current_bw = %d, bitrate = %d\n", current_bandwidth, bitrate);
+      next_variant = current_variant;
+
+      /*  Go to the highest possible bandwidth allowed */
+      while ((current_bandwidth + BITRATE_SWITCH_UPPER_THRESHOLD * current_bandwidth) < bitrate) {
+        current_variant = next_variant;
+        next_variant = g_list_next (next_variant);
+        if (!next_variant) {
+          GST_DEBUG ("no next upper fragment...\n");
+          GST_M3U8_CLIENT_UNLOCK (client);
+          return current_variant;
+        }
+
+        current_bandwidth = GST_M3U8 (next_variant->data)->bandwidth;
+        GST_DEBUG ("current_bw in while= %d & URI = %s\n", current_bandwidth, GST_M3U8 (next_variant->data)->uri);
+      }
+
+      /* as condition failed fallback to previous */
+      GST_M3U8_CLIENT_UNLOCK (client);
+
+      return current_variant;
+    }
+  } else if ((current_bandwidth + BITRATE_SWITCH_LOWER_THRESHOLD * current_bandwidth) > bitrate) {
+    GST_DEBUG ("Switch to lower band...\n");
+
+    if (!g_list_previous (current_variant)) {
+      GST_DEBUG ("no previous lower fragment...to go further down\n");
+      GST_M3U8_CLIENT_UNLOCK (client);
+      return current_variant;
+    } else {
+
+      GST_DEBUG (">>>>> LOW : current_bw = %d, bitrate = %d\n", current_bandwidth, bitrate);
+      next_variant = current_variant;
+
+      /*  Go to the lowest possible bandwidth allowed */
+      while ((current_bandwidth + BITRATE_SWITCH_LOWER_THRESHOLD * current_bandwidth) > bitrate) {
+
+        next_variant = g_list_previous (next_variant);
+        if (!next_variant) {
+          GST_DEBUG ("no previous lower fragment...\n");
+          GST_M3U8_CLIENT_UNLOCK (client);
+          return current_variant;
+        }
+
+        current_variant = next_variant;
+
+        current_bandwidth = GST_M3U8 (current_variant->data)->bandwidth;
+        GST_DEBUG ("current_bw in while= %d\n", current_bandwidth);
+      }
+
+      GST_M3U8_CLIENT_UNLOCK (client);
+
+      /* as condition failed fallback to previous */
+      return current_variant;
+    }
+  } else {
+    GST_DEBUG ("No need to switch .... returning current_variant..\n");
+  }
+
+  GST_M3U8_CLIENT_UNLOCK (client);
+
+  return current_variant;
+}
+#endif
+
+gboolean
+gst_m3u8_client_decrypt_init (GstM3U8Client * client, unsigned char *key, gchar *iv)
+{
+  //if (!client->current->cipher_ctx)
+ //   client->current->cipher_ctx = g_malloc0 (sizeof(EVP_CIPHER_CTX));
+
+  EVP_CIPHER_CTX_init (&(client->cipher_ctx));
+  EVP_CIPHER_CTX_set_padding(&(client->cipher_ctx), 0); // added to check avodining final buffer decryption error
+
+  return EVP_DecryptInit_ex (&(client->cipher_ctx), EVP_aes_128_cbc(), NULL, key, iv);
+}
+
+gboolean
+gst_m3u8_client_decrypt_update (GstM3U8Client * client, guint8 * out_data,
+    gint * out_size, guint8 * in_data, gint in_size)
+{
+  //g_return_val_if_fail (client->current->cipher_ctx != NULL, FALSE);
+
+  return EVP_DecryptUpdate (&(client->cipher_ctx), out_data, out_size,
+      in_data, in_size);
+}
+
+gboolean
+gst_m3u8_client_decrypt_final (GstM3U8Client * client, guint8 * out_data,
+    gint * out_size)
+{
+  //g_return_val_if_fail (client->current->cipher_ctx != NULL, FALSE);
+
+  return EVP_DecryptFinal_ex (&(client->cipher_ctx), out_data, out_size);
+}
+
+gboolean
+gst_m3u8_client_decrypt_deinit (GstM3U8Client * client)
+{
+  //g_return_val_if_fail (client->current->cipher_ctx != NULL, FALSE);
+
+  return EVP_CIPHER_CTX_cleanup (&(client->cipher_ctx));
+}
+
+
+gboolean
+gst_m3u8_client_is_playlist_download_needed (GstM3U8Client * self)
+{
+  /* download is not need, if last_data is present & not live (i.e. we can reuse last VOD child playlist)*/
+  if (self->current->last_data && !gst_m3u8_client_is_live(self))
+    return FALSE;
+  else
+    return TRUE;
+}
diff --git a/hlsdemux2/src/m3u8.h b/hlsdemux2/src/m3u8.h
new file mode 100755 (executable)
index 0000000..d2a67e2
--- /dev/null
@@ -0,0 +1,137 @@
+/* GStreamer
+ * Copyright (C) 2010 Marc-Andre Lureau <marcandre.lureau@gmail.com>
+ * Copyright (C) 2010 Andoni Morales Alastruey <ylatuya@gmail.com>
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * m3u8.h:
+ *
+ * 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 __M3U8_H__
+#define __M3U8_H__
+
+#include <glib.h>
+#include <openssl/evp.h>
+#include <gst/gst.h>
+
+G_BEGIN_DECLS typedef struct _GstM3U8 GstM3U8;
+typedef struct _GstM3U8MediaFile GstM3U8MediaFile;
+typedef struct _GstM3U8Key GstM3U8Key;
+typedef struct _GstM3U8Client GstM3U8Client;
+
+#define GST_M3U8(m) ((GstM3U8*)m)
+#define GST_M3U8_KEY(k) ((GstM3U8Key*)k)
+#define GST_M3U8_MEDIA_FILE(f) ((GstM3U8MediaFile*)f)
+
+#define GST_M3U8_CLIENT_LOCK(c) g_mutex_lock (c->lock);
+#define GST_M3U8_CLIENT_UNLOCK(c) g_mutex_unlock (c->lock);
+
+#define GST_M3U8_IV_LEN 16
+
+GST_DEBUG_CATEGORY_EXTERN (hlsdemux2_m3u8_debug);
+
+typedef enum {
+  GST_M3U8_ENCRYPTED_NONE,
+  GST_M3U8_ENCRYPTED_AES_128,
+} GstM3U8EncryptionMethod;
+
+struct _GstM3U8
+{
+  gchar *uri;
+
+  gboolean endlist;             /* if ENDLIST has been reached */
+  gint version;                 /* last EXT-X-VERSION */
+  GstClockTime targetduration;  /* last EXT-X-TARGETDURATION */
+  gchar *allowcache;            /* last EXT-X-ALLOWCACHE */
+
+  gint bandwidth;
+  gint program_id;
+  gchar *codecs;
+  gint width;
+  gint height;
+  GList *files;
+
+  /*< private > */
+  gchar *last_data;
+  GList *lists;                 /* list of GstM3U8 from the main playlist */
+  GList *current_variant;       /* Current variant playlist used */
+  GstM3U8 *parent;              /* main playlist (if any) */
+  guint mediasequence;          /* EXT-X-MEDIA-SEQUENCE & increased with new media file */
+};
+
+struct _GstM3U8MediaFile
+{
+  gchar *title;
+  GstClockTime duration;
+  gchar *uri;
+  guint sequence;               /* the sequence nb of this file */
+  gchar *key_url;
+  unsigned char *key;
+  unsigned char *iv;
+};
+
+struct _GstM3U8Key
+{
+  GstM3U8EncryptionMethod method;
+  gchar *uri;
+  guint8 *iv;
+  guint sequence;
+  guint8 *data;
+};
+
+struct _GstM3U8Client
+{
+  GstM3U8 *main;                /* main playlist */
+  GstM3U8 *current;
+  guint update_failed_count;
+  gint sequence;                /* the next sequence for this client */
+  GMutex *lock;
+  EVP_CIPHER_CTX cipher_ctx;
+};
+
+
+GstM3U8Client *gst_m3u8_client_new (const gchar * uri);
+void gst_m3u8_client_free (GstM3U8Client * client);
+gboolean gst_m3u8_client_update (GstM3U8Client * client, gchar * data);
+void gst_m3u8_client_set_current (GstM3U8Client * client, GstM3U8 * m3u8);
+gboolean gst_m3u8_client_get_next_fragment (GstM3U8Client * client, GstClockTime cur_running_time,
+    gboolean * discontinuity, const gchar ** uri, GstClockTime * duration,
+    GstClockTime * timestamp, gchar **key_uri, gchar **iv);
+void gst_m3u8_client_get_current_position (GstM3U8Client * client,
+    GstClockTime * timestamp);
+GstClockTime gst_m3u8_client_get_duration (GstM3U8Client * client);
+GstClockTime gst_m3u8_client_get_target_duration (GstM3U8Client * client);
+const gchar *gst_m3u8_client_get_uri(GstM3U8Client * client);
+const gchar *gst_m3u8_client_get_current_uri(GstM3U8Client * client);
+gboolean gst_m3u8_client_has_variant_playlist(GstM3U8Client * client);
+gboolean gst_m3u8_client_is_live(GstM3U8Client * client);
+GList * gst_m3u8_client_get_playlist_for_bitrate (GstM3U8Client * client,
+    guint bitrate);
+gboolean gst_m3u8_client_decrypt_init (GstM3U8Client * client, unsigned char *key, gchar *iv);
+gboolean gst_m3u8_client_decrypt_update (GstM3U8Client * client,
+    guint8 * out_data, gint * out_size, guint8 * in_data, gint in_size);
+gboolean gst_m3u8_client_is_playlist_download_needed (GstM3U8Client * self);
+GstClockTime gst_m3u8_client_get_last_fragment_duration (GstM3U8Client * client);
+gint gst_m3u8_client_get_current_bandwidth (GstM3U8Client * client);
+gboolean gst_m3u8_client_decrypt_final (GstM3U8Client * client, guint8 * out_data, gint * out_size);
+gboolean gst_m3u8_client_decrypt_deinit (GstM3U8Client * client);
+void gst_m3u8_client_decrement_sequence (GstM3U8Client * client);
+GList *gst_m3u8_client_get_next_higher_bw_playlist (GstM3U8Client * client);
+GList *gst_m3u8_client_get_next_lower_bw_playlist (GstM3U8Client * client);
+
+G_END_DECLS
+#endif /* __M3U8_H__ */
index e57fa95..46b821d 100644 (file)
@@ -1,19 +1,33 @@
 Name:       gst-plugins-ext0.10
-Version:     0.2.4
-Summary:  GStreamer extra plugins (common)
-Release:    1
-Group:      TO_BE/FILLED_IN
-License:    TO BE FILLED IN
+Version:    0.4.88
+Summary:    GStreamer extra plugins (common)
+Release:    0
+Group:      libs
+License:    LGPL-2.1+
 Source0:    %{name}-%{version}.tar.gz
-BuildRequires:  pkgconfig(avsysaudio)
 BuildRequires:  pkgconfig(camsrcjpegenc)
+#BuildRequires:  pkgconfig(drm-client)
+#BuildRequires:  pkgconfig(drm-trusted)
 BuildRequires:  pkgconfig(ecore)
 BuildRequires:  pkgconfig(ecore-x)
 BuildRequires:  pkgconfig(evas)
-BuildRequires:  pkgconfig(mm-ta)
+BuildRequires:  gst-plugins-base-devel 
 BuildRequires:  pkgconfig(gstreamer-plugins-base-0.10)
-BuildRequires:  pkgconfig(gstreamer-0.10)  
+BuildRequires:  pkgconfig(gstreamer-0.10)
 BuildRequires:  pkgconfig(libexif)
+BuildRequires:  pkgconfig(libxml-2.0)
+BuildRequires: pkgconfig(libdri2)
+BuildRequires: pkgconfig(x11)
+BuildRequires: pkgconfig(xext)
+BuildRequires: pkgconfig(xv)
+BuildRequires: pkgconfig(xdamage)
+BuildRequires: pkgconfig(libdrm)
+BuildRequires:  pkgconfig(libtbm)
+BuildRequires: pkgconfig(dri2proto)
+BuildRequires: pkgconfig(xfixes)
+BuildRequires: pkgconfig(libtbm)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(libcrypto)
 
 %description
 GStreamer extra plugins (common)
@@ -23,18 +37,31 @@ GStreamer extra plugins (common)
 
 
 %build
-export CFLAGS+=" -DGST_EXT_TIME_ANALYSIS -DEXPORT_API=\"__attribute__((visibility(\\\"default\\\")))\" "
+export CFLAGS+=" -DCONTROL_PAGECACHE -DGST_EXT_TIME_ANALYSIS -DEXPORT_API=\"__attribute__((visibility(\\\"default\\\")))\" "
 
 ./autogen.sh --disable-static
-%configure --disable-static
+%configure --disable-static \
+ --enable-ext-hlsdemux2\
+ --disable-ext-drmsrc\
+%if 0%{?tizen_build_binary_release_type_eng}
+ --enable-pcmdump
+%endif
 
 make %{?jobs:-j%jobs}
 
 %install
 rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+cp COPYING %{buildroot}/usr/share/license/%{name}
 %make_install
-
+mkdir -p %{buildroot}/usr/etc/
+install -m 755 hlsdemux2/predefined_frame/* %{buildroot}/usr/etc/
 
 %files
-%defattr(-,root,root,-)  
+%manifest gst-plugins-ext0.10.manifest
+%defattr(-,root,root,-)
 %{_libdir}/gstreamer-0.10/*.so
+/usr/share/license/%{name}
+/usr/etc/blackframe_QVGA.264
+/usr/etc/sec_audio_fixed_qvga.264
+/usr/etc/sec_audio_fixed_qvga.jpg
index a5ed22f..29efdc1 100755 (executable)
@@ -166,14 +166,14 @@ gst_pd_pushsrc_class_init (GstPDPushSrcClass * klass)
           "Location of the file to read", NULL,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
           GST_PARAM_MUTABLE_READY));
-   
+
     g_object_class_install_property (gobject_class, ARG_EOS,
                                     g_param_spec_boolean ("eos",
                                         "EOS recived on downloading pipeline",
                                         "download of clip is over",
                                         0,
                                         G_PARAM_READWRITE));
-   
+
   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_pd_pushsrc_start);
   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_pd_pushsrc_stop);
   gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_pd_pushsrc_is_seekable);
@@ -187,7 +187,7 @@ gst_pd_pushsrc_class_init (GstPDPushSrcClass * klass)
   }
 
   GST_LOG ("OUT");
+
 }
 
 static void
@@ -201,7 +201,7 @@ gst_pd_pushsrc_init (GstPDPushSrc * src, GstPDPushSrcClass * g_class)
   src->uri = NULL;
   src->is_regular = FALSE;
   src->is_eos = FALSE;
-  
+
   gst_pad_set_checkgetrange_function (basesrc->srcpad, GST_DEBUG_FUNCPTR (gst_pd_pushsrc_checkgetrange));
 
   GST_LOG ("OUT");
@@ -255,7 +255,7 @@ gst_pd_pushsrc_set_location (GstPDPushSrc * src, const gchar * location)
   }
   g_object_notify (G_OBJECT (src), "location");
   gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
-  
+
   GST_LOG ("OUT");
 
   return TRUE;
@@ -328,17 +328,20 @@ gst_pd_pushsrc_create_read (GstBaseSrc * basesrc, guint64 offset, guint length,
   GST_LOG ("IN");
 
   int ret;
-  GstBuffer *buf;
+  GstBuffer *buf = NULL;
   struct stat stat_results;
   GstPDPushSrc *src;
 
+  if(length < 1)
+    return GST_FLOW_ERROR;
+
   src = GST_PD_PUSHSRC_CAST (basesrc);
-  
-  GST_LOG_OBJECT (src, "read position = %"G_GUINT64_FORMAT ", offset = %"G_GUINT64_FORMAT", length = %d", 
-       src->read_position, offset, length);
-  
+
+  GST_LOG_OBJECT (src, "read position = %"G_GUINT64_FORMAT ", offset = %"G_GUINT64_FORMAT", length = %d",
+    src->read_position, offset, length);
+
   memset (&stat_results, 0, sizeof (stat_results));
-  
+
   if (fstat (src->fd, &stat_results) < 0)
     goto could_not_stat;
 
@@ -363,9 +366,9 @@ gst_pd_pushsrc_create_read (GstBaseSrc * basesrc, guint64 offset, guint length,
     GST_DEBUG_OBJECT (src, "Going to wait for %ld msec", timeout.tv_usec);
 
     ret = select (src->fd + 1, &fds, NULL, NULL, &timeout);
-    if (-1 == ret) 
+    if (-1 == ret)
     {
-      GST_ERROR_OBJECT (src, "ERROR in select () : reason - %s...\n", strerror(errno));
+      GST_ERROR_OBJECT (src, "ERROR in select () : reason - %s...\n", g_strerror(errno));
       return GST_FLOW_ERROR;
     }
     else if (0 == ret)
@@ -375,7 +378,7 @@ gst_pd_pushsrc_create_read (GstBaseSrc * basesrc, guint64 offset, guint length,
     else
     {
       memset (&stat_results, 0, sizeof (stat_results));
-  
+
       if (fstat (src->fd, &stat_results) < 0)
         goto could_not_stat;
 
@@ -402,36 +405,33 @@ gst_pd_pushsrc_create_read (GstBaseSrc * basesrc, guint64 offset, guint length,
       goto seek_failed;
     src->read_position = offset;
   }
-  
+
   buf = gst_buffer_try_new_and_alloc (length);
-  if (G_UNLIKELY (buf == NULL && length > 0)) {
+  if (G_UNLIKELY (buf == NULL)) {
     GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", length);
     return GST_FLOW_ERROR;
   }
 
-  /* No need to read anything if length is 0 */
-  if (length > 0) {
-    GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x",
-        length, offset);
-    ret = read (src->fd, GST_BUFFER_DATA (buf), length);
-    if (G_UNLIKELY (ret < 0))
-      goto could_not_read;
+  GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x",
+      length, offset);
+  ret = read (src->fd, GST_BUFFER_DATA (buf), length);
+  if (G_UNLIKELY (ret < 0))
+    goto could_not_read;
 
-    /* seekable regular files should have given us what we expected */
-    if (G_UNLIKELY ((guint) ret < length && src->seekable))
-      goto unexpected_eos;
+  /* seekable regular files should have given us what we expected */
+  if (G_UNLIKELY ((guint) ret < length && src->seekable))
+    goto unexpected_eos;
 
-    /* other files should eos if they read 0 and more was requested */
-    if (G_UNLIKELY (ret == 0 && length > 0))
-      goto eos;
+  /* other files should eos if they read 0 and more was requested */
+  if (G_UNLIKELY (ret == 0 && length > 0))
+    goto eos;
 
-    length = ret;
-    GST_BUFFER_SIZE (buf) = length;
-    GST_BUFFER_OFFSET (buf) = offset;
-    GST_BUFFER_OFFSET_END (buf) = offset + length;
+  length = ret;
+  GST_BUFFER_SIZE (buf) = length;
+  GST_BUFFER_OFFSET (buf) = offset;
+  GST_BUFFER_OFFSET_END (buf) = offset + length;
 
-    src->read_position += length;
-  }
+  src->read_position += length;
 
   *buffer = buf;
   GST_LOG ("OUT");
@@ -461,15 +461,15 @@ could_not_read:
 unexpected_eos:
   {
     GST_ERROR_OBJECT (src, "Unexpected EOS occured...");
-    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
-        ("unexpected end of file."));
+    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("unexpected end of file."));
     gst_buffer_unref (buf);
     return GST_FLOW_ERROR;
   }
 eos:
   {
     GST_ERROR_OBJECT (src, "non-regular file hits EOS");
-    gst_buffer_unref (buf);
+    if (buf)
+      gst_buffer_unref (buf);
     return GST_FLOW_UNEXPECTED;
   }
 }
@@ -562,7 +562,7 @@ gst_pd_pushsrc_get_size (GstBaseSrc * basesrc, guint64 * size)
   *size = G_MAXUINT64;
 
   GST_DEBUG ("size of the file = %"G_GUINT64_FORMAT, *size);
-  
+
   GST_LOG ("OUT");
 
   return TRUE;
@@ -658,7 +658,7 @@ open_failed:
   }
 no_stat:
   {
-    GST_ERROR_OBJECT (src, "Could not get stat info...");      
+    GST_ERROR_OBJECT (src, "Could not get stat info...");
     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
         ("Could not get info on \"\"."),  (NULL));
     close (src->fd);
@@ -674,7 +674,7 @@ was_directory:
   }
 was_socket:
   {
-   GST_ERROR_OBJECT (src, "Is a Socket");      
+   GST_ERROR_OBJECT (src, "Is a Socket");
     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
         ("File \"\" is a socket."), (NULL));
     close (src->fd);
@@ -772,7 +772,7 @@ gst_pd_pushsrc_uri_set_uri (GstURIHandler * handler, const gchar * uri)
 #ifdef G_OS_WIN32
   /* Unfortunately, g_filename_from_uri() doesn't handle some UNC paths
    * correctly on windows, it leaves them with an extra backslash
-   * at the start if they're of the mozilla-style file://///host/path/file 
+   * at the start if they're of the mozilla-style file://///host/path/file
    * form. Correct this.
    */
   if (location[0] == '\\' && location[1] == '\\' && location[2] == '\\')
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..a966f06
--- /dev/null
@@ -0,0 +1,47 @@
+
+plugin_LTLIBRARIES = libgstpiff.la
+
+libgstpiffincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/
+
+libgstpiff_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(DRM_CLIENT_CFLAGS) $(DRM_TRUSTED_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) $(DRM_CLIENT_LIBS) $(DRM_TRUSTED_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 \
+    piffcommon.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..ee96f6e
--- /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, "LGPL",  "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..aa8c196
--- /dev/null
@@ -0,0 +1,3273 @@
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "piffdemux.h"
+#include <glib/gprintf.h>
+#include <gst/tag/tag.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <piffatomparser.h>
+#include <piffdemux_fourcc.h>
+#include <piffpalette.h>
+#include <piffdemux_types.h>
+#include <piffdemux_dump.h>
+
+#define PIFF_DEFAULT_TRACKID   -1
+#define PIFF_DEFAULT_FOURCC   0
+#define PIFF_DEFAULT_TIMESCALE 10000000
+#define PIFF_DEFAULT_DURATION -1
+#define PIFF_DEFAULT_START_TS 0
+#define PIFF_DEFAULT_START_TS 0
+
+#define PIFF_DEFAULT_WIDTH 16
+#define PIFF_DEFAULT_HEIGHT 16
+#define PIFF_DEFAULT_BPS 16
+
+#undef DEC_OUT_FRAME_DUMP
+
+#ifdef DEC_OUT_FRAME_DUMP
+#include <stdio.h>
+FILE *piffdump = NULL;
+#endif
+
+#define PIFFDEMUX_RB16(x)      ((((const unsigned char*)(x))[0] << 8) | ((const unsigned char*)(x))[1])
+/* max. size considered 'sane' for non-mdat atoms */
+#define PIFFDEMUX_MAX_ATOM_SIZE (25*1024*1024)
+
+/* if the sample index is larger than this, something is likely wrong */
+#define PIFFDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
+
+GST_DEBUG_CATEGORY (piffdemux_debug);
+
+typedef struct _PiffDemuxSegment PiffDemuxSegment;
+typedef struct _PiffDemuxSample PiffDemuxSample;
+typedef struct _PiffDemuxSubSampleEncryption PiffDemuxSubSampleEncryption;
+typedef struct _PiffDemuxSubSampleEntryInfo PiffDemuxSubSampleEntryInfo;
+
+enum
+{
+  PROR_PIFF_0,
+  PROP_PIFF_MEDIA_CAPS,
+  PROP_PIFF_MEDIA_TIMESCALE,
+  PROP_PIFF_MEDIA_DURATION,
+  PROP_PIFF_MEDIA_START_TIMESTAMP,
+  PROP_PIFF_IS_LIVE,
+  PROP_PIFF_LOOKAHEAD_COUNT,
+  PROP_PIFF_AVG_FRAME_DUR,
+#ifdef DRM_ENABLE
+  PROP_PROTECTION_HEADER_BUFFER,
+#endif
+};
+
+enum
+{
+  SIGNAL_LIVE_PARAM,
+  LAST_SIGNAL
+};
+
+static guint gst_piffdemux_signals[LAST_SIGNAL] = { 0 };
+
+struct _PiffDemuxSubSampleEntryInfo
+{
+  guint16 LenofClearData;
+  guint32 LenofEncryptData;
+};
+
+struct _PiffDemuxSubSampleEncryption
+{
+  guint16 n_entries;
+  PiffDemuxSubSampleEntryInfo *sub_entry;
+};
+
+struct _PiffDemuxSample
+{
+  guint32 size;
+  gint32 pts_offset;            /* Add this value to timestamp to get the pts */
+  guint64 offset;
+  guint64 timestamp;            /* DTS In mov time */
+  guint32 duration;             /* In mov time */
+  gboolean keyframe;            /* TRUE when this packet is a keyframe */
+  guint8 *iv;                          /* initialization vector for decryption*/
+  PiffDemuxSubSampleEncryption *sub_encry;
+};
+
+/* timestamp is the DTS */
+#define PIFFSAMPLE_DTS(stream,sample) gst_util_uint64_scale ((sample)->timestamp,\
+    GST_SECOND, (stream)->timescale)
+/* timestamp + offset is the PTS */
+#define PIFFSAMPLE_PTS(stream,sample) gst_util_uint64_scale ((sample)->timestamp + \
+    (sample)->pts_offset, GST_SECOND, (stream)->timescale)
+/* timestamp + duration - dts is the duration */
+#define PIFFSAMPLE_DUR_DTS(stream,sample,dts) (gst_util_uint64_scale ((sample)->timestamp + \
+    (sample)->duration, GST_SECOND, (stream)->timescale) - (dts));
+/* timestamp + offset + duration - pts is the duration */
+#define PIFFSAMPLE_DUR_PTS(stream,sample,pts) (gst_util_uint64_scale ((sample)->timestamp + \
+    (sample)->pts_offset + (sample)->duration, GST_SECOND, (stream)->timescale) - (pts));
+
+#define PIFFSAMPLE_KEYFRAME(stream,sample) ((sample)->keyframe);
+
+typedef char uuid_t[16];
+
+static const uuid_t tfxd_uuid = { 0x6d, 0x1d, 0x9b, 0x05,
+                                               0x42, 0xd5, 0x44, 0xe6,
+                                               0x80, 0xe2, 0x14, 0x1d,
+                                               0xaf, 0xf7, 0x57, 0xb2 };
+
+static const uuid_t tfrf_uuid = { 0xd4, 0x80, 0x7e, 0xf2,
+                                              0xca, 0x39, 0x46, 0x95,
+                                              0x8e, 0x54, 0x26, 0xcb,
+                                              0x9e, 0x46, 0xa7, 0x9f };
+
+static const uuid_t encrypt_uuid = {  0xa2, 0x39, 0x4f, 0x52,
+                                                        0x5a, 0x9b, 0x4f, 0x14,
+                                                        0xa2, 0x44, 0x6c, 0x42,
+                                                        0x7c, 0x64, 0x8d, 0xf4 };
+
+#define SE_OVERRIDE_TE_FLAGS 0x000001
+#define SE_USE_SUBSAMPLE_ENCRYPTION 0x000002
+
+typedef enum
+{
+  UUID_UNKNOWN = -1,
+  UUID_TFXD,
+  UUID_TFRF,
+  UUID_SAMPLE_ENCRYPT,
+}uuid_type_t;
+
+struct _PiffDemuxSegment
+{
+  /* global time and duration, all gst time */
+  guint64 time;
+  guint64 stop_time;
+  guint64 duration;
+  /* media time of trak, all gst time */
+  guint64 media_start;
+  guint64 media_stop;
+  gdouble rate;
+};
+
+
+struct _PiffDemuxStream
+{
+  /* stream type */
+  guint32 subtype;
+  GstCaps *caps;
+  guint32 fourcc;
+
+  /* duration/scale */
+  guint64 duration;             /* in timescale */
+  guint32 timescale;
+
+  /* our samples */
+  guint32 n_samples;
+  PiffDemuxSample *samples;
+  guint32 min_duration;         /* duration in timescale of first sample, used for figuring out
+                                   the framerate, in timescale units */
+
+  /* if we use chunks or samples */
+  gboolean sampled;
+  guint padding;
+
+  /* when a discontinuity is pending */
+  gboolean discont;
+
+  /* list of buffers to push first */
+  GSList *buffers;
+
+  /* buffer needs some custom processing, e.g. subtitles */
+  gboolean need_process;
+
+    /* current position */
+  guint32 segment_index;
+  guint32 sample_index;
+  guint64 time_position;        /* in gst time */
+
+  /* the Gst segment we are processing out, used for clipping */
+  GstSegment segment;
+
+  /* last GstFlowReturn */
+  GstFlowReturn last_ret;
+
+
+  /* quicktime segments */
+  guint32 n_segments;
+  PiffDemuxSegment *segments;
+  guint32 from_sample;
+  guint32 to_sample;
+
+  gboolean sent_eos;
+  GstTagList *pending_tags;
+  gboolean send_global_tags;
+
+  GstEvent *pending_event;
+
+  gboolean sent_nsevent;
+
+  guint64 start_ts;
+
+  guint64 avg_dur; /* average frame duration */
+};
+
+
+enum PiffDemuxState
+{
+  PIFFDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */
+  PIFFDEMUX_STATE_HEADER,         /* Parsing the header */
+  PIFFDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */
+  PIFFDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */
+};
+
+
+static GNode *piffdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
+static GNode *piffdemux_tree_get_child_by_type_full (GNode * node,
+    guint32 fourcc, GstByteReader * parser);
+static GNode *piffdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
+static GNode *piffdemux_tree_get_sibling_by_type_full (GNode * node,
+    guint32 fourcc, GstByteReader * parser);
+
+static GstStaticPadTemplate gst_piffdemux_sink_template =
+    GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("application/x-piff")
+    );
+
+static GstStaticPadTemplate gst_piffdemux_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+
+GST_BOILERPLATE (GstPiffDemux, gst_piffdemux, GstPiffDemux, GST_TYPE_ELEMENT);
+
+static void gst_piffdemux_dispose (GObject * object);
+
+static GstStateChangeReturn gst_piffdemux_change_state (GstElement * element,
+    GstStateChange transition);
+static void
+gst_piffdemux_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void
+gst_piffdemux_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+static GstFlowReturn gst_piffdemux_chain (GstPad * sinkpad, GstBuffer * inbuf);
+static gboolean gst_piffdemux_handle_sink_event (GstPad * pad, GstEvent * event);
+static gboolean piffdemux_parse_node (GstPiffDemux * piffdemux, GNode * node, const guint8 * buffer, guint length);
+static gboolean piffdemux_parse_sample_encryption(GstPiffDemux * piffdemux, GstByteReader *sample_encrypt, PiffDemuxStream * stream);
+static gboolean piffdemux_parse_mfhd (GstPiffDemux * piffdemux, GstByteReader * mfhd);
+static gboolean gst_piffdemux_handle_src_event (GstPad * pad, GstEvent * event);
+static const GstQueryType *gst_piffdemux_get_src_query_types (GstPad * pad);
+static gboolean gst_piffdemux_handle_src_query (GstPad * pad, GstQuery * query);
+
+#ifdef DRM_ENABLE
+static void piffdemux_get_playready_licence (GstPiffDemux *demux);
+void test_drm_trusted_operation_cb(drm_trusted_user_operation_info_s *operation_info, void *output_data);
+#endif
+
+static gboolean
+ConvertH264_MetaDCI_to_3GPPDCI(unsigned char *dci_meta_buf, unsigned int dci_meta_size, unsigned char **dci_3gpp_buf, unsigned int *dci_3gpp_size);
+void
+__gst_piffdemux_marshal_BOOLEAN__OBJECT (GClosure *closure,
+                                   GValue       *return_value G_GNUC_UNUSED,
+                                   guint         n_param_values,
+                                   const GValue *param_values,
+                                   gpointer      invocation_hint G_GNUC_UNUSED,
+                                   gpointer      marshal_data);
+
+static void
+gst_piffdemux_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_piffdemux_sink_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_piffdemux_src_template));
+  gst_element_class_set_details_simple (element_class, "PIFF demuxer",
+      "Codec/Parser",
+      "Parser for PIFF file format",
+      "naveen ch <naveen.ch@samsung.com>");
+
+  GST_DEBUG_CATEGORY_INIT (piffdemux_debug, "piffdemux", 0, "piffdemux plugin");
+}
+
+static void
+gst_piffdemux_class_init (GstPiffDemuxClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->dispose = gst_piffdemux_dispose;
+  gobject_class->set_property = gst_piffdemux_set_property;
+  gobject_class->get_property = gst_piffdemux_get_property;
+
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_piffdemux_change_state);
+
+  g_object_class_install_property (gobject_class, PROP_PIFF_MEDIA_CAPS,
+                                   g_param_spec_boxed ("caps", "Caps",
+                                   "The allowed caps for the src pad", GST_TYPE_CAPS,
+                                   G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /* timescale of media to be set by application */
+  g_object_class_install_property (gobject_class, PROP_PIFF_MEDIA_TIMESCALE,
+                                   g_param_spec_uint64 ("timescale", "media timescale",
+                                   "media timescale in PIFF Manifest", 0, G_MAXUINT64,
+                                   PIFF_DEFAULT_TIMESCALE,
+                                   G_PARAM_READWRITE));
+#ifdef DRM_ENABLE
+  g_object_class_install_property (gobject_class, PROP_PROTECTION_HEADER_BUFFER,
+                                   gst_param_spec_mini_object ("protection-header", "protection header buffer",
+                                   "protection header used for playready", GST_TYPE_BUFFER,
+                                   G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
+  g_object_class_install_property (gobject_class, PROP_PIFF_MEDIA_DURATION,
+                                   g_param_spec_int64 ("duration", "Duration of media",
+                                   "Total duration of the content", -1, G_MAXINT64,
+                                   PIFF_DEFAULT_DURATION,
+                                   G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_PIFF_MEDIA_START_TIMESTAMP,
+                                   g_param_spec_uint64 ("start-ts", "expected start timestamp",
+                                   "expected start timestamp to avoid reset", 0, G_MAXUINT64,
+                                   PIFF_DEFAULT_START_TS,
+                                   G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_PIFF_IS_LIVE,
+                                   g_param_spec_boolean ("is-live", "Is presentation is Live or VOD",
+                                   "If Presentation is Live (true) else VOD (false)",
+                                   FALSE, G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_PIFF_LOOKAHEAD_COUNT,
+                                   g_param_spec_uint ("lookahead-count", "Lookahead count value",
+                                  "Look ahead count used in case of Live presentation", 0, G_MAXUINT,
+                                  0, G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_PIFF_AVG_FRAME_DUR,
+                                   g_param_spec_uint64 ("frame-dur", "Average frame duration",
+                                   "Average frame duration", 0, G_MAXUINT64,
+                                   G_MAXUINT64,
+                                   G_PARAM_READABLE));
+
+  gst_piffdemux_signals[SIGNAL_LIVE_PARAM] = g_signal_new ("live-param",
+                                                           G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+                                                           G_STRUCT_OFFSET (GstPiffDemuxClass, live_param), NULL, NULL,
+                                                           g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+}
+
+
+static void
+gst_piffdemux_init (GstPiffDemux * piffdemux, GstPiffDemuxClass * klass)
+{
+  /* sink pad */
+  piffdemux->sinkpad = gst_pad_new_from_static_template (&gst_piffdemux_sink_template, "sink");
+  gst_pad_set_chain_function (piffdemux->sinkpad, gst_piffdemux_chain);
+  gst_pad_set_event_function (piffdemux->sinkpad, gst_piffdemux_handle_sink_event);
+  gst_element_add_pad (GST_ELEMENT_CAST (piffdemux), piffdemux->sinkpad);
+
+  /* source pad */
+  piffdemux->srcpad = gst_pad_new_from_static_template (&gst_piffdemux_src_template, "src");
+  gst_pad_set_event_function (piffdemux->srcpad, gst_piffdemux_handle_src_event);
+  gst_pad_use_fixed_caps (piffdemux->srcpad);
+  gst_pad_set_query_type_function (piffdemux->srcpad, gst_piffdemux_get_src_query_types);
+  gst_pad_set_query_function (piffdemux->srcpad, gst_piffdemux_handle_src_query);
+  gst_element_add_pad (GST_ELEMENT_CAST (piffdemux), piffdemux->srcpad);
+
+  piffdemux->stream = g_new0 (PiffDemuxStream, 1);
+  piffdemux->stream->fourcc = PIFF_DEFAULT_FOURCC;
+  piffdemux->stream->timescale = PIFF_DEFAULT_TIMESCALE;
+  piffdemux->stream->duration = PIFF_DEFAULT_DURATION;
+  piffdemux->stream->caps = NULL;
+  piffdemux->stream->discont = TRUE;
+  piffdemux->stream->need_process = FALSE;
+  piffdemux->stream->segment_index = -1;
+  piffdemux->stream->time_position = 0;
+  piffdemux->stream->sample_index = -1;
+  piffdemux->stream->last_ret = GST_FLOW_OK;
+  piffdemux->stream->sent_nsevent = FALSE;
+  piffdemux->stream->start_ts = PIFF_DEFAULT_START_TS;
+  piffdemux->stream->avg_dur = -1;
+
+  piffdemux->state = PIFFDEMUX_STATE_INITIAL;
+  piffdemux->neededbytes = 16;
+  piffdemux->todrop = 0;
+  piffdemux->adapter = gst_adapter_new ();
+  piffdemux->offset = 0;
+  piffdemux->first_mdat = -1;
+  piffdemux->mdatoffset = GST_CLOCK_TIME_NONE;
+  piffdemux->mdatbuffer = NULL;
+  piffdemux->moof_rcvd = FALSE;
+  piffdemux->is_live = FALSE;
+  piffdemux->lookahead_cnt = 0;
+#ifdef DRM_ENABLE
+  piffdemux->pr_handle = NULL;
+#endif
+  piffdemux->decrypt_init = FALSE;
+  piffdemux->encrypt_content = FALSE;
+
+#ifdef DEC_OUT_FRAME_DUMP
+    piffdump = fopen ("/opt/media/piff_out_dump.dmp", "w+");
+    if (piffdump == NULL)
+    {
+        g_print ("\nNot able to create frame dump file\n");
+    }
+#endif
+
+  gst_segment_init (&piffdemux->segment, GST_FORMAT_TIME);
+}
+
+static void
+gst_piffdemux_dispose (GObject * object)
+{
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (object);
+
+  if (piffdemux->adapter) {
+    g_object_unref (G_OBJECT (piffdemux->adapter));
+    piffdemux->adapter = NULL;
+  }
+
+#ifdef DEC_OUT_FRAME_DUMP
+    {
+        fclose (piffdump);
+        piffdump = NULL;
+    }
+#endif
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+
+static void
+gst_piffdemux_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (object);
+
+  switch (prop_id) {
+    case PROP_PIFF_MEDIA_CAPS: {
+      if (piffdemux->stream->caps)
+        gst_caps_unref(piffdemux->stream->caps);
+      piffdemux->stream->caps = gst_caps_copy (gst_value_get_caps (value));
+      gchar *caps_string = gst_caps_to_string(piffdemux->stream->caps);
+      GST_DEBUG_OBJECT (piffdemux, "stream caps = %s", caps_string);
+      g_free(caps_string);
+      caps_string = NULL;
+      if (!gst_pad_set_caps(piffdemux->srcpad, piffdemux->stream->caps)) {
+        GST_ERROR_OBJECT (piffdemux, "not able to set caps...");
+      }
+      break;
+    }
+    case PROP_PIFF_MEDIA_TIMESCALE:
+      piffdemux->stream->timescale = g_value_get_uint64(value);
+      break;
+    case PROP_PIFF_MEDIA_DURATION:
+      piffdemux->stream->duration = g_value_get_int64(value);
+      break;
+    case PROP_PIFF_MEDIA_START_TIMESTAMP:
+      piffdemux->stream->start_ts = g_value_get_uint64(value);
+      GST_INFO_OBJECT (piffdemux, "start_ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(piffdemux->stream->start_ts));
+      break;
+    case PROP_PIFF_IS_LIVE:
+      piffdemux->is_live = g_value_get_boolean(value);
+      break;
+    case PROP_PIFF_LOOKAHEAD_COUNT:
+      piffdemux->lookahead_cnt = g_value_get_uint(value);
+      GST_DEBUG_OBJECT (piffdemux, "Look ahead count = %d", piffdemux->lookahead_cnt);
+      break;
+#ifdef DRM_ENABLE
+    case PROP_PROTECTION_HEADER_BUFFER:
+      piffdemux->protection_header = gst_value_get_buffer(value);
+      piffdemux_get_playready_licence (piffdemux);
+      break;
+#endif
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+static void
+gst_piffdemux_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (object);
+
+  switch (prop_id) {
+     case PROP_PIFF_MEDIA_CAPS:
+      gst_value_set_caps (value, piffdemux->stream->caps);
+      break;
+    case PROP_PIFF_MEDIA_TIMESCALE:
+      g_value_set_uint64 (value, piffdemux->stream->timescale);
+      break;
+    case PROP_PIFF_MEDIA_DURATION:
+      g_value_set_int64 (value, piffdemux->stream->duration);
+      break;
+    case PROP_PIFF_MEDIA_START_TIMESTAMP:
+      g_value_set_uint64 (value, piffdemux->stream->start_ts);
+      break;
+    case PROP_PIFF_IS_LIVE:
+      g_value_set_boolean(value, piffdemux->is_live);
+      break;
+    case PROP_PIFF_LOOKAHEAD_COUNT:
+      g_value_set_uint (value, piffdemux->lookahead_cnt);
+      break;
+    case PROP_PIFF_AVG_FRAME_DUR:
+      g_value_set_uint64 (value, piffdemux->stream->avg_dur);
+      break;
+#ifdef DRM_ENABLE
+    case PROP_PROTECTION_HEADER_BUFFER:
+      gst_value_take_buffer (value, piffdemux->protection_header);
+      break;
+#endif
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+static void
+gst_piffdemux_post_no_playable_stream_error (GstPiffDemux * piffdemux)
+{
+  if (piffdemux->posted_redirect) {
+    GST_ELEMENT_ERROR (piffdemux, STREAM, DEMUX,
+        ("This file contains no playable streams."),
+        ("no known streams found, a redirect message has been posted"));
+  } else {
+    GST_ELEMENT_ERROR (piffdemux, STREAM, DEMUX,
+        ("This file contains no playable streams."),
+        ("no known streams found"));
+  }
+
+}
+
+static gboolean
+gst_piffdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
+    GstFormat dest_format, gint64 * dest_value)
+{
+  gboolean res = TRUE;
+  PiffDemuxStream *stream = gst_pad_get_element_private (pad);
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (gst_pad_get_parent (pad));
+
+  if (stream->subtype != FOURCC_vide) {
+    res = FALSE;
+    goto done;
+  }
+
+  switch (src_format) {
+    case GST_FORMAT_TIME:
+      switch (dest_format) {
+        case GST_FORMAT_BYTES:{
+
+          break;
+        }
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    case GST_FORMAT_BYTES:
+      switch (dest_format) {
+        case GST_FORMAT_TIME:{
+
+          break;
+        }
+        default:
+          res = FALSE;
+          break;
+      }
+      break;
+    default:
+      res = FALSE;
+  }
+
+done:
+  gst_object_unref (piffdemux);
+
+  return res;
+}
+
+static const GstQueryType *
+gst_piffdemux_get_src_query_types (GstPad * pad)
+{
+  static const GstQueryType src_types[] = {
+    GST_QUERY_POSITION,
+    GST_QUERY_DURATION,
+    GST_QUERY_CONVERT,
+    GST_QUERY_FORMATS,
+    GST_QUERY_SEEKING,
+    0
+  };
+
+  return src_types;
+}
+
+static gboolean
+gst_piffdemux_get_duration (GstPiffDemux * piffdemux, gint64 * duration)
+{
+  gboolean res = TRUE;
+
+  *duration = GST_CLOCK_TIME_NONE;
+
+  if (piffdemux->stream->duration != 0) {
+    if (piffdemux->stream->duration != G_MAXINT64 && piffdemux->stream->timescale != 0) {
+      *duration = gst_util_uint64_scale (piffdemux->stream->duration,
+          GST_SECOND, piffdemux->stream->timescale);
+    }
+  }
+  return res;
+}
+
+static gboolean
+gst_piffdemux_handle_src_query (GstPad * pad, GstQuery * query)
+{
+  gboolean res = FALSE;
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (gst_pad_get_parent (pad));
+
+  GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_POSITION:
+      GST_ERROR ("Querying POSITION from piffdemux....");
+      if (GST_CLOCK_TIME_IS_VALID (piffdemux->segment.last_stop)) {
+        gst_query_set_position (query, GST_FORMAT_TIME,
+            piffdemux->segment.last_stop);
+        res = TRUE;
+      }
+      break;
+    case GST_QUERY_DURATION:{
+      GstFormat fmt;
+      GST_ERROR ("Querying DURATION from piffdemux....");
+
+      gst_query_parse_duration (query, &fmt, NULL);
+      if (fmt == GST_FORMAT_TIME) {
+        gint64 duration = -1;
+
+        gst_piffdemux_get_duration (piffdemux, &duration);
+        if (duration > 0) {
+          gst_query_set_duration (query, GST_FORMAT_TIME, duration);
+          res = TRUE;
+        }
+      }
+      break;
+    }
+    case GST_QUERY_CONVERT:{
+      GstFormat src_fmt, dest_fmt;
+      gint64 src_value, dest_value = 0;
+
+      gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
+
+      res = gst_piffdemux_src_convert (pad,
+          src_fmt, src_value, dest_fmt, &dest_value);
+      if (res) {
+        gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
+        res = TRUE;
+      }
+      break;
+    }
+    case GST_QUERY_FORMATS:
+      gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
+      res = TRUE;
+      break;
+    case GST_QUERY_SEEKING:{
+
+      break;
+    }
+    default:
+      res = gst_pad_query_default (pad, query);
+      break;
+  }
+
+  gst_object_unref (piffdemux);
+
+  return res;
+}
+
+
+static void
+gst_piffdemux_push_tags (GstPiffDemux * piffdemux, PiffDemuxStream * stream)
+{
+  if (G_UNLIKELY (stream->pending_tags)) {
+    GST_DEBUG_OBJECT (piffdemux, "Sending tags %" GST_PTR_FORMAT,
+        stream->pending_tags);
+    gst_pad_push_event (piffdemux->srcpad,
+        gst_event_new_tag (stream->pending_tags));
+    stream->pending_tags = NULL;
+  }
+
+  if (G_UNLIKELY (stream->send_global_tags && piffdemux->tag_list)) {
+    GST_DEBUG_OBJECT (piffdemux, "Sending global tags %" GST_PTR_FORMAT,
+        piffdemux->tag_list);
+    gst_pad_push_event (piffdemux->srcpad,
+        gst_event_new_tag (gst_tag_list_copy (piffdemux->tag_list)));
+    stream->send_global_tags = FALSE;
+  }
+}
+
+
+static void
+gst_piffdemux_push_event (GstPiffDemux * piffdemux, GstEvent * event)
+{
+  GstEventType etype = GST_EVENT_TYPE (event);
+
+  GST_DEBUG_OBJECT (piffdemux, "pushing %s event on source pad",
+      GST_EVENT_TYPE_NAME (event));
+
+  if (piffdemux->stream->sent_eos) {
+    GST_INFO_OBJECT (piffdemux, "already sent eos");
+    return;
+  }
+
+  if (!gst_pad_push_event (piffdemux->srcpad, event)) {
+    GST_ERROR_OBJECT (piffdemux, "error in sending event to srcpad...");
+  }
+
+  if (etype == GST_EVENT_EOS)
+    piffdemux->stream->sent_eos = TRUE;
+}
+
+
+/* find the segment for @time_position for @stream
+ *
+ * Returns -1 if the segment cannot be found.
+ */
+static guint32
+gst_piffdemux_find_segment (GstPiffDemux * piffdemux, PiffDemuxStream * stream,
+    guint64 time_position)
+{
+  gint i;
+  guint32 seg_idx;
+
+  GST_LOG_OBJECT (piffdemux, "finding segment for %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (time_position));
+
+  /* find segment corresponding to time_position if we are looking
+   * for a segment. */
+  seg_idx = -1;
+  for (i = 0; i < stream->n_segments; i++) {
+    PiffDemuxSegment *segment = &stream->segments[i];
+
+    GST_LOG_OBJECT (piffdemux,
+        "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
+        GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
+
+    /* For the last segment we include stop_time in the last segment */
+    if (i < stream->n_segments - 1) {
+      if (segment->time <= time_position && time_position < segment->stop_time) {
+        GST_LOG_OBJECT (piffdemux, "segment %d matches", i);
+        seg_idx = i;
+        break;
+      }
+    } else {
+      if (segment->time <= time_position && time_position <= segment->stop_time) {
+        GST_LOG_OBJECT (piffdemux, "segment %d matches", i);
+        seg_idx = i;
+        break;
+      }
+    }
+  }
+  return seg_idx;
+}
+
+
+static gboolean
+gst_piffdemux_handle_src_event (GstPad * pad, GstEvent * event)
+{
+  gboolean res = TRUE;
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (gst_pad_get_parent (pad));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_QOS:
+    case GST_EVENT_NAVIGATION:
+      res = FALSE;
+      gst_event_unref (event);
+      break;
+    case GST_EVENT_SEEK:
+    default:
+      res = gst_pad_event_default (pad, event);
+      break;
+  }
+
+  gst_object_unref (piffdemux);
+
+  return res;
+}
+
+
+static void
+gst_piffdemux_move_stream (GstPiffDemux * piffdemux, PiffDemuxStream * str,
+    guint32 index)
+{
+  /* no change needed */
+  if (index == str->sample_index)
+    return;
+
+  GST_DEBUG_OBJECT (piffdemux, "moving to sample %u of %u", index,
+      str->n_samples);
+
+  /* position changed, we have a discont */
+  str->sample_index = index;
+  /* Each time we move in the stream we store the position where we are
+   * starting from */
+  str->from_sample = index;
+  str->discont = TRUE;
+}
+
+// TODO: need to check more on this below function
+/* stream/index return sample that is min/max w.r.t. byte position,
+ * time is min/max w.r.t. time of samples,
+ * the latter need not be time of the former sample */
+static void
+gst_piffdemux_find_sample (GstPiffDemux * piffdemux, gint64 byte_pos, gboolean fw,
+    gboolean set, PiffDemuxStream ** _stream, gint * _index, gint64 * _time)
+{
+  gint i, index;
+  gint64 time, min_time;
+  PiffDemuxStream *stream;
+  PiffDemuxStream *str = piffdemux->stream;
+  gint inc;
+  gboolean set_sample;
+
+  min_time = -1;
+  stream = NULL;
+  index = -1;
+
+  set_sample = !set;
+  if (fw) {
+    i = 0;
+    inc = 1;
+  } else {
+    i = str->n_samples - 1;
+    inc = -1;
+  }
+
+  for (; (i >= 0) && (i < str->n_samples); i += inc) {
+    if (str->samples[i].size &&
+    ((fw && (str->samples[i].offset >= byte_pos)) ||
+    (!fw &&
+    (str->samples[i].offset + str->samples[i].size <=
+    byte_pos)))) {
+      /* move stream to first available sample */
+      if (set) {
+        gst_piffdemux_move_stream (piffdemux, str, i);
+        set_sample = TRUE;
+      }
+      /* determine min/max time */
+      time = str->samples[i].timestamp + str->samples[i].pts_offset;
+      time = gst_util_uint64_scale (time, GST_SECOND, str->timescale);
+      /*if (min_time == -1 || (!fw && time > min_time) ||
+      (fw && time < min_time)) : Dead code*/ {
+        min_time = time;
+      }
+      index = i;
+      break;
+    }
+  }
+  /* no sample for this stream, mark eos */
+  if (!set_sample)
+    gst_piffdemux_move_stream (piffdemux, str, str->n_samples);
+
+  if (_time)
+    *_time = min_time;
+  if (_stream)
+    *_stream = str;
+  if (_index)
+    *_index = index;
+}
+
+
+static gboolean
+gst_piffdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
+{
+  GstPiffDemux *demux = GST_PIFFDEMUX (GST_PAD_PARENT (sinkpad));
+  gboolean res;
+
+  GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_NEWSEGMENT:
+    {
+      GstFormat format;
+      gdouble rate, arate;
+      gint64 start, stop, time, offset = 0;
+      PiffDemuxStream *stream;
+      gint idx;
+      gboolean update;
+      GstSegment segment;
+
+      /* some debug output */
+      gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
+      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
+          &start, &stop, &time);
+      gst_segment_set_newsegment_full (&segment, update, rate, arate, format,
+          start, stop, time);
+      GST_ERROR_OBJECT (demux,
+          "received format %d newsegment %" GST_SEGMENT_FORMAT, format,
+          &segment);
+
+      /* chain will send initial newsegment after pads have been added */
+      if (demux->state != PIFFDEMUX_STATE_MOVIE ) {
+        GST_DEBUG_OBJECT (demux, "still starting, eating event");
+        goto exit;
+      }
+
+      /* we only expect a BYTE segment, e.g. following a seek */
+      if (format == GST_FORMAT_BYTES) {
+        if (start > 0) {
+          gint64 requested_seek_time;
+          guint64 seek_offset;
+
+          offset = start;
+
+          GST_OBJECT_LOCK (demux);
+          requested_seek_time = demux->requested_seek_time;
+          seek_offset = demux->seek_offset;
+          demux->requested_seek_time = -1;
+          demux->seek_offset = -1;
+          GST_OBJECT_UNLOCK (demux);
+
+          if (offset == seek_offset) {
+            start = requested_seek_time;
+          } else {
+            gst_piffdemux_find_sample (demux, start, TRUE, FALSE, NULL, NULL,
+                &start);
+            start = MAX (start, 0);
+          }
+        }
+        if (stop > 0) {
+          gst_piffdemux_find_sample (demux, stop, FALSE, FALSE, NULL, NULL,
+              &stop);
+          /* keyframe seeking should already arrange for start >= stop,
+           * but make sure in other rare cases */
+          stop = MAX (stop, start);
+        }
+      }
+#if 0
+      else if (format == GST_FORMAT_TIME) {
+          // Supporting TIME_FORMAT for new_segment
+          //gst_piffdemux_push_event (demux,event);
+        PiffDemuxStream *stream = NULL;
+        int i = -1;
+
+          demux->neededbytes = 16;
+          demux->state = PIFFDEMUX_STATE_INITIAL;
+          demux->offset = 0;
+
+        /* Figure out which stream this is packet belongs to */
+        for (i = 0; i < demux->n_streams; i++) {
+          stream = demux->streams[i];
+          stream->last_ts = start;
+          stream->discont = TRUE;
+          stream->sample_index = stream->n_samples;
+        }
+
+           /* accept upstream's notion of segment and distribute along */
+          gst_segment_set_newsegment_full (&demux->segment, update, rate, arate,
+              GST_FORMAT_TIME, start, stop, start);
+          GST_ERROR_OBJECT (demux, "Pushing newseg update %d, rate %g, "
+              "applied rate %g, format %d, start %" GST_TIME_FORMAT ", "
+              "stop %" GST_TIME_FORMAT, update, rate, arate, GST_FORMAT_TIME,
+              GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
+
+          gst_piffdemux_push_event (demux,
+              gst_event_new_new_segment_full (update, rate, arate, GST_FORMAT_TIME, start, stop, start));
+
+           /* clear leftover in current segment, if any */
+          gst_adapter_clear (demux->adapter);
+
+          goto exit;
+      }
+#endif
+      else {
+        GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
+        goto exit;
+      }
+
+      /* accept upstream's notion of segment and distribute along */
+      gst_segment_set_newsegment_full (&demux->segment, update, rate, arate,
+          GST_FORMAT_TIME, start, stop, start);
+      GST_ERROR_OBJECT (demux, "Pushing newseg update %d, rate %g, "
+          "applied rate %g, format %d, start %" GST_TIME_FORMAT ", "
+          "stop %" GST_TIME_FORMAT, update, rate, arate, GST_FORMAT_TIME,
+          GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
+
+      gst_piffdemux_push_event (demux,
+          gst_event_new_new_segment_full (update, rate, arate, GST_FORMAT_TIME,
+              start, stop, start));
+
+      /* clear leftover in current segment, if any */
+      gst_adapter_clear (demux->adapter);
+      /* set up streaming thread */
+      gst_piffdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx, NULL);
+      demux->offset = offset;
+      if (stream) {
+        demux->todrop = stream->samples[idx].offset - offset;
+        demux->neededbytes = demux->todrop + stream->samples[idx].size;
+      } else {
+        /* set up for EOS */
+        demux->neededbytes = -1;
+        demux->todrop = 0;
+      }
+    exit:
+      gst_event_unref (event);
+      res = TRUE;
+      goto drop;
+      break;
+    }
+    case GST_EVENT_FLUSH_STOP:
+    {
+      /* clean up, force EOS if no more info follows */
+      gst_adapter_clear (demux->adapter);
+      demux->offset = 0;
+      demux->neededbytes = -1;
+      /* reset flow return, e.g. following seek */
+      demux->stream->last_ret = GST_FLOW_OK;
+      demux->stream->sent_eos = FALSE;
+      break;
+    }
+    case GST_EVENT_EOS:
+      break;
+    default:
+      break;
+  }
+
+  res = gst_pad_event_default (demux->sinkpad, event);
+
+drop:
+  return res;
+}
+
+
+static void
+gst_piffdemux_stream_free (GstPiffDemux * piffdemux, PiffDemuxStream * stream)
+{
+  int i = 0;
+
+  g_return_if_fail (stream != NULL);
+
+  while (stream->buffers) {
+    gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
+    stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
+  }
+
+  for (i = 0; i < stream->n_samples; i++) {
+    if (stream->samples[i].iv) {
+      free (stream->samples[i].iv);
+      stream->samples[i].iv = NULL;
+    }
+    if (stream->samples[i].sub_encry) {
+      if (stream->samples[i].sub_encry->sub_entry) {
+        g_free (stream->samples[i].sub_encry->sub_entry);
+        stream->samples[i].sub_encry->sub_entry = NULL;
+      }
+
+      free (stream->samples[i].sub_encry);
+      stream->samples[i].sub_encry = NULL;
+    }
+  }
+
+  if (stream->samples) {
+    g_free (stream->samples);
+    stream->samples = NULL;
+  }
+  if (stream->caps) {
+    gst_caps_unref (stream->caps);
+    stream->caps = NULL;
+  }
+  if (stream->segments) {
+    g_free (stream->segments);
+    stream->segments = NULL;
+  }
+  if (stream->pending_tags) {
+    gst_tag_list_free (stream->pending_tags);
+    stream->pending_tags = NULL;
+  }
+  g_free (stream);
+}
+
+
+static GstStateChangeReturn
+gst_piffdemux_change_state (GstElement * element, GstStateChange transition)
+{
+  GstPiffDemux *piffdemux = GST_PIFFDEMUX (element);
+  GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      break;
+    default:
+      break;
+  }
+
+  result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:{
+      piffdemux->state = PIFFDEMUX_STATE_INITIAL;
+      piffdemux->neededbytes = 16;
+      piffdemux->todrop = 0;
+      piffdemux->posted_redirect = FALSE;
+      piffdemux->offset = 0;
+      piffdemux->first_mdat = -1;
+      piffdemux->mdatoffset = GST_CLOCK_TIME_NONE;
+      if (piffdemux->mdatbuffer)
+        gst_buffer_unref (piffdemux->mdatbuffer);
+      piffdemux->mdatbuffer = NULL;
+      if (piffdemux->tag_list)
+        gst_tag_list_free (piffdemux->tag_list);
+      piffdemux->tag_list = NULL;
+      gst_adapter_clear (piffdemux->adapter);
+      gst_piffdemux_stream_free (piffdemux, piffdemux->stream);
+      gst_segment_init (&piffdemux->segment, GST_FORMAT_TIME);
+      break;
+    }
+    default:
+      break;
+  }
+
+  return result;
+}
+
+static void
+piffdemux_post_global_tags (GstPiffDemux * piffdemux)
+{
+  if (piffdemux->tag_list) {
+    /* all header tags ready and parsed, push them */
+    GST_INFO_OBJECT (piffdemux, "posting global tags: %" GST_PTR_FORMAT,
+        piffdemux->tag_list);
+    /* post now, send event on pads later */
+    gst_element_post_message (GST_ELEMENT (piffdemux),
+        gst_message_new_tag (GST_OBJECT (piffdemux),
+            gst_tag_list_copy (piffdemux->tag_list)));
+  }
+}
+
+
+/* caller verifies at least 8 bytes in buf */
+static void
+extract_initial_length_and_fourcc (const guint8 * data, guint size,
+    guint64 * plength, guint32 * pfourcc)
+{
+  guint64 length;
+  guint32 fourcc;
+
+  length = PIFF_UINT32 (data);
+  GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
+  fourcc = PIFF_FOURCC (data + 4);
+  GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
+
+  if (length == 0) {
+    length = G_MAXUINT32;
+  } else if (length == 1 && size >= 16) {
+    /* this means we have an extended size, which is the 64 bit value of
+     * the next 8 bytes */
+    length = PIFF_UINT64 (data + 8);
+    GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
+  }
+
+  if (plength)
+    *plength = length;
+  if (pfourcc)
+    *pfourcc = fourcc;
+}
+
+static gboolean
+piffdemux_update_sample_offset (GstPiffDemux * piffdemu, PiffDemuxStream * stream, gint64 uuid_offset)
+{
+  PiffDemuxSample *sample;
+  gint i;
+
+  sample = stream->samples ;
+  for (i = 0; i < stream->n_samples; i++)
+  {
+    sample->offset = sample->offset + uuid_offset;
+    sample++;
+  }
+  return TRUE;
+}
+
+static uuid_type_t
+piffdemux_get_uuid_type(GstPiffDemux * piffdemux, GstByteReader *uuid_data, gint64 *uuid_offset)
+{
+  uuid_type_t uuid_type = UUID_UNKNOWN;
+  guint32 box_len = 0;
+  guint64 box_long_len = 0;
+  gchar uuid[16] = {0,};
+  int i = 0;
+
+  if (!gst_byte_reader_get_uint32_be (uuid_data, &box_len))
+    goto invalid_uuid;
+
+  /* Skipping fourcc */
+  if (!gst_byte_reader_skip (uuid_data, 4))
+    goto invalid_uuid;
+
+  if (box_len == 1)
+  {
+    GST_WARNING ("TfxdBoxLongLength field is present...");
+    if (!gst_byte_reader_get_uint64_be (uuid_data, &box_long_len))
+      goto invalid_uuid;
+    GST_DEBUG ("tfxd long length = %llu", box_long_len);
+
+    *uuid_offset = box_long_len;
+  }
+  else
+  {
+    GST_DEBUG ("Box Len = %d", box_len);
+    *uuid_offset = box_len;
+  }
+
+  //g_print ("\n\n\n 0x");
+  for (i = 0; i < sizeof (uuid); i++)
+  {
+    if (!gst_byte_reader_get_uint8 (uuid_data, &(uuid[i])))
+      goto invalid_uuid;
+    //g_print ("%02x", uuid[i]);
+  }
+  //g_print ("\n\n\n");
+
+  if (!memcmp(uuid, tfxd_uuid, sizeof (uuid_t)))
+  {
+    GST_INFO ("Found TFXD box");
+    return UUID_TFXD;
+  }
+  else if (!memcmp(uuid, tfrf_uuid, sizeof (uuid_t)))
+  {
+    GST_INFO ("Found TFRF box");
+    return UUID_TFRF;
+  }
+  else if (!memcmp(uuid, encrypt_uuid, sizeof (uuid_t)))
+  {
+    GST_INFO ("Found sample encryption box");
+    return UUID_SAMPLE_ENCRYPT;
+  }
+  else
+  {
+    GST_WARNING ("Not an valid UUID box..");
+    goto invalid_uuid;
+  }
+  return uuid_type;
+
+invalid_uuid:
+  GST_ERROR ("Error in parsing UUID atom...");
+  return UUID_UNKNOWN;
+}
+
+static gboolean
+piffdemux_parse_sample_encryption(GstPiffDemux * piffdemux, GstByteReader *sample_encrypt, PiffDemuxStream * stream)
+{
+  guint32 flags = 0;
+  guint32 sample_count = 0;
+  guint32 i = 0;
+  guint32 algo_id;
+  guint8 iv_size = 0;
+
+  if (!gst_byte_reader_skip (sample_encrypt, 1) ||
+      !gst_byte_reader_get_uint24_be (sample_encrypt, &flags))
+    goto invalid_encryption;
+
+  if (flags & SE_OVERRIDE_TE_FLAGS) {
+    /* get algorithm id */
+    if (!gst_byte_reader_get_uint32_be (sample_encrypt, &algo_id))
+      goto invalid_encryption;
+
+    /* get IV size */
+    if (!gst_byte_reader_get_uint8 (sample_encrypt, &iv_size))
+      goto invalid_encryption;
+
+    // TODO: need to add reading of KID
+  } else {
+    GST_INFO_OBJECT (piffdemux, "Override flags are not present... taking default IV_Size = 8");
+    iv_size = 8;
+  }
+
+  /* Get sample count*/
+  if (!gst_byte_reader_get_uint32_be (sample_encrypt, &sample_count))
+    goto invalid_encryption;
+
+  GST_INFO_OBJECT (piffdemux, "Sample count = %d", sample_count);
+
+  if (sample_count != stream->n_samples) {
+    GST_ERROR_OBJECT (piffdemux, "Not all samples has IV vectors... Don't know how to handle. sample_cnt = %d and stream->n_samples = %d",
+      sample_count, stream->n_samples);
+    goto invalid_encryption;
+  }
+
+  for (i = 0; i < stream->n_samples; i++) {
+    guint8 iv_idx = iv_size;
+
+    /* resetting entire IV array */
+    stream->samples[i].iv = (guint8 *)malloc (iv_size);
+    if (NULL == stream->samples[i].iv) {
+      GST_ERROR ("Failed to allocate memory...\n");
+      goto invalid_encryption;
+    }
+
+    memset (stream->samples[i].iv, 0x00, iv_size);
+
+    iv_idx = 0;
+    while (iv_idx < iv_size) {
+      /* get IV byte */
+      if (!gst_byte_reader_get_uint8 (sample_encrypt, &(stream->samples[i].iv[iv_idx])))
+        goto invalid_encryption;
+
+      iv_idx++;
+    }
+
+#ifdef DEBUG_IV
+  {
+    guint8 tmp_idx = 0;
+    g_print ("sample[%d] : 0x ", i);
+
+    while (tmp_idx < iv_size ) {
+      g_print ("%02x ", stream->samples[i].iv[tmp_idx]);
+      tmp_idx++;
+    }
+    g_print ("\n");
+  }
+#endif
+
+    if (flags & SE_USE_SUBSAMPLE_ENCRYPTION) {
+      guint16 n_entries;
+      guint16 n_idx;
+
+      /* NumberofEntries in SubSampleEncryption */
+      if (!gst_byte_reader_get_uint16_be (sample_encrypt, &n_entries))
+        goto invalid_encryption;
+
+      stream->samples[i].sub_encry = (PiffDemuxSubSampleEncryption *)malloc (sizeof (PiffDemuxSubSampleEncryption));
+      if (NULL == stream->samples[i].sub_encry) {
+        GST_ERROR ("Failed to allocate memory...\n");
+        goto invalid_encryption;
+      }
+
+      stream->samples[i].sub_encry->sub_entry = g_try_new0 (PiffDemuxSubSampleEntryInfo, n_entries);
+      if (NULL == stream->samples[i].sub_encry->sub_entry) {
+        GST_ERROR_OBJECT (piffdemux, "Failed to allocate memory...");
+        goto invalid_encryption;
+      }
+
+      stream->samples[i].sub_encry->n_entries = n_entries;
+
+      GST_DEBUG_OBJECT (piffdemux,"No. of subsample entries = %d", stream->samples[i].sub_encry->n_entries);
+
+      for (n_idx = 0; n_idx < n_entries; n_idx++) {
+        if (!gst_byte_reader_get_uint16_be (sample_encrypt, &(stream->samples[i].sub_encry->sub_entry[n_idx].LenofClearData)))
+          goto invalid_encryption;
+
+        GST_DEBUG_OBJECT (piffdemux,"entry[%d] and lengthofClearData = %d", n_idx, stream->samples[i].sub_encry->sub_entry[n_idx].LenofClearData);
+
+        if (!gst_byte_reader_get_uint32_be (sample_encrypt, &(stream->samples[i].sub_encry->sub_entry[n_idx].LenofEncryptData)))
+          goto invalid_encryption;
+
+        GST_DEBUG_OBJECT (piffdemux,"entry[%d] and lengthofEncryptData = %d", n_idx, stream->samples[i].sub_encry->sub_entry[n_idx].LenofEncryptData);
+      }
+    }
+  }
+
+  return TRUE;
+
+invalid_encryption:
+  {
+    GST_WARNING_OBJECT (piffdemux, "invalid sample encryption header");
+    return FALSE;
+  }
+}
+
+
+static gboolean
+piffdemux_parse_trun (GstPiffDemux * piffdemux, GstByteReader * trun,
+    PiffDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
+    guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
+    gint64 * base_offset, gint64 * running_offset)
+{
+  guint64 timestamp;
+  gint32 data_offset = 0;
+  guint32 flags = 0, first_flags = 0, samples_count = 0;
+  gint i;
+  guint8 *data;
+  guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
+  PiffDemuxSample *sample;
+  gboolean ismv = FALSE;
+  guint64 total_duration = 0;
+
+  GST_LOG_OBJECT (piffdemux, "parsing trun stream ; "
+      "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT,
+       d_sample_duration, d_sample_size, d_sample_flags,
+      *base_offset);
+
+  //Resetting the samples
+  stream->n_samples = 0;
+
+  if (!gst_byte_reader_skip (trun, 1) ||
+      !gst_byte_reader_get_uint24_be (trun, &flags))
+    goto fail;
+
+  if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
+    goto fail;
+
+  if (flags & TR_DATA_OFFSET) {
+    /* note this is really signed */
+    if (!gst_byte_reader_get_int32_be (trun, &data_offset))
+      goto fail;
+    GST_LOG_OBJECT (piffdemux, "trun data offset %d", data_offset);
+    /* default base offset = first byte of moof */
+    if (*base_offset == -1) {
+      GST_LOG_OBJECT (piffdemux, "base_offset at moof and moof_offset = %"G_GINT64_FORMAT, moof_offset);
+      *base_offset = moof_offset;
+    }
+    *running_offset = *base_offset + data_offset;
+  } else {
+    /* if no offset at all, that would mean data starts at moof start,
+     * which is a bit wrong and is ismv crappy way, so compensate
+     * assuming data is in mdat following moof */
+    if (*base_offset == -1) {
+      *base_offset = moof_offset + moof_length + 8;
+      GST_LOG_OBJECT (piffdemux, "base_offset assumed in mdat after moof");
+      ismv = TRUE;
+    }
+    if (*running_offset == -1)
+      *running_offset = *base_offset;
+  }
+
+  GST_LOG_OBJECT (piffdemux, "running offset now %" G_GINT64_FORMAT,
+      *running_offset);
+  GST_LOG_OBJECT (piffdemux, "trun offset %d, flags 0x%x, entries %d",
+      data_offset, flags, samples_count);
+
+  if (flags & TR_FIRST_SAMPLE_FLAGS) {
+    if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
+      GST_DEBUG_OBJECT (piffdemux,
+          "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
+      flags ^= TR_FIRST_SAMPLE_FLAGS;
+    } else {
+      if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
+        goto fail;
+      GST_LOG_OBJECT (piffdemux, "first flags: 0x%x", first_flags);
+    }
+  }
+
+  /* FIXME ? spec says other bits should also be checked to determine
+   * entry size (and prefix size for that matter) */
+  entry_size = 0;
+  dur_offset = size_offset = 0;
+  if (flags & TR_SAMPLE_DURATION) {
+    GST_LOG_OBJECT (piffdemux, "entry duration present");
+    dur_offset = entry_size;
+    entry_size += 4;
+  }
+  if (flags & TR_SAMPLE_SIZE) {
+    GST_LOG_OBJECT (piffdemux, "entry size present");
+    size_offset = entry_size;
+    entry_size += 4;
+  }
+  if (flags & TR_SAMPLE_FLAGS) {
+    GST_LOG_OBJECT (piffdemux, "entry flags present");
+    flags_offset = entry_size;
+    entry_size += 4;
+  }
+  if (flags & TR_COMPOSITION_TIME_OFFSETS) {
+    GST_LOG_OBJECT (piffdemux, "entry ct offset present");
+    ct_offset = entry_size;
+    entry_size += 4;
+  }
+
+  if (!piff_atom_parser_has_chunks (trun, samples_count, entry_size))
+    goto fail;
+  data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
+
+  if (stream->n_samples >=
+      PIFFDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (PiffDemuxSample))
+    goto index_too_big;
+
+  GST_DEBUG_OBJECT (piffdemux, "allocating n_samples %u * %u (%.2f MB)",
+      stream->n_samples, (guint) sizeof (PiffDemuxSample),
+      stream->n_samples * sizeof (PiffDemuxSample) / (1024.0 * 1024.0));
+
+  /* create a new array of samples if it's the first sample parsed */
+  if (stream->n_samples == 0)
+    stream->samples = g_try_new0 (PiffDemuxSample, samples_count);
+  /* or try to reallocate it with space enough to insert the new samples */
+  else
+    stream->samples = g_try_renew (PiffDemuxSample, stream->samples,
+        stream->n_samples + samples_count);
+  if (stream->samples == NULL)
+    goto out_of_memory;
+
+  if (G_UNLIKELY (stream->n_samples == 0)) {
+    /* the timestamp of the first sample is also provided by the tfra entry
+     * but we shouldn't rely on it as it is at the end of files */
+    timestamp = 0;
+  } else {
+    /* subsequent fragments extend stream */
+    timestamp =
+        stream->samples[stream->n_samples - 1].timestamp +
+        stream->samples[stream->n_samples - 1].duration;
+  }
+  sample = stream->samples + stream->n_samples;
+  for (i = 0; i < samples_count; i++) {
+    guint32 dur, size, sflags, ct;
+
+    /* first read sample data */
+    if (flags & TR_SAMPLE_DURATION) {
+      dur = PIFF_UINT32 (data + dur_offset);
+    } else {
+      dur = d_sample_duration;
+    }
+    if (flags & TR_SAMPLE_SIZE) {
+      size = PIFF_UINT32 (data + size_offset);
+    } else {
+      size = d_sample_size;
+    }
+
+    GST_DEBUG_OBJECT(piffdemux,"Size of sample %d is %d", i, size);
+
+    if (flags & TR_FIRST_SAMPLE_FLAGS) {
+      if (i == 0) {
+        sflags = first_flags;
+      } else {
+        sflags = d_sample_flags;
+      }
+    } else if (flags & TR_SAMPLE_FLAGS) {
+      sflags = PIFF_UINT32 (data + flags_offset);
+    } else {
+      sflags = d_sample_flags;
+    }
+    if (flags & TR_COMPOSITION_TIME_OFFSETS) {
+      ct = PIFF_UINT32 (data + ct_offset);
+    } else {
+      ct = 0;
+    }
+    data += entry_size;
+
+    /* fill the sample information */
+    sample->offset = *running_offset;
+    sample->pts_offset = ct;
+    sample->size = size;
+    sample->timestamp = timestamp;
+    sample->duration = dur;
+    /* sample-is-difference-sample */
+    /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
+     * now idea how it relates to bitfield other than massive LE/BE confusion */
+    sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
+    sample->iv = NULL;
+    sample->sub_encry = NULL;
+
+    stream->samples[i] = *sample;
+
+    *running_offset += size;
+    timestamp += dur;
+    sample++;
+
+    /* calculate total duration of the present fragment */
+    total_duration += gst_util_uint64_scale (dur, GST_SECOND, stream->timescale);
+  }
+
+  stream->sample_index = 0;
+
+  stream->n_samples += samples_count;
+
+  /* calculate avg fps based on avg frame duration */
+  stream->avg_dur = total_duration/samples_count;
+  g_print ("total dur = %"GST_TIME_FORMAT", avg_dur = %"GST_TIME_FORMAT"count = %d\n",
+       GST_TIME_ARGS(total_duration), GST_TIME_ARGS(stream->avg_dur), samples_count);
+
+  return TRUE;
+
+fail:
+  {
+    GST_WARNING_OBJECT (piffdemux, "failed to parse trun");
+    return FALSE;
+  }
+out_of_memory:
+  {
+    GST_WARNING_OBJECT (piffdemux, "failed to allocate %d samples",
+        stream->n_samples);
+    return FALSE;
+  }
+index_too_big:
+  {
+    GST_WARNING_OBJECT (piffdemux, "not allocating index of %d samples, would "
+        "be larger than %uMB (broken file?)", stream->n_samples,
+        PIFFDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
+    return FALSE;
+  }
+}
+
+static gboolean
+piffdemux_parse_mfhd (GstPiffDemux * piffdemux, GstByteReader * mfhd)
+{
+  guint32 seq_num = 0;
+
+  if (!gst_byte_reader_skip (mfhd, 4))
+    goto invalid_mfhd;
+
+  if (!gst_byte_reader_get_uint32_be (mfhd, &seq_num))
+    goto invalid_mfhd;
+
+  GST_DEBUG_OBJECT (piffdemux, "sequence number present in mfhd = %d", seq_num);
+
+  return TRUE;
+
+invalid_mfhd:
+  {
+    GST_WARNING_OBJECT (piffdemux, "invalid movie fragment header");
+    return FALSE;
+  }
+}
+
+
+static gboolean
+piffdemux_parse_tfhd (GstPiffDemux * piffdemux, GstByteReader * tfhd,
+    guint32 * default_sample_duration,
+    guint32 * default_sample_size, guint32 * default_sample_flags,
+    gint64 * base_offset)
+{
+  guint32 flags = 0;
+  guint32 track_id = 0;
+
+  if (!gst_byte_reader_skip (tfhd, 1) ||
+      !gst_byte_reader_get_uint24_be (tfhd, &flags))
+    goto invalid_track;
+
+  if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
+    goto invalid_track;
+
+  GST_DEBUG_OBJECT (piffdemux, "trackID = %d", track_id);
+
+  if (flags & TF_BASE_DATA_OFFSET) {
+    if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
+      goto invalid_track;
+    GST_DEBUG ("BaseData Offset = %"G_GUINT64_FORMAT, base_offset);
+  }
+
+  /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
+  if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
+    if (!gst_byte_reader_skip (tfhd, 4))
+      goto invalid_track;
+
+  if (flags & TF_DEFAULT_SAMPLE_DURATION)
+    if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
+      goto invalid_track;
+
+  if (flags & TF_DEFAULT_SAMPLE_SIZE)
+    if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
+      goto invalid_track;
+
+  if (flags & TF_DEFAULT_SAMPLE_FLAGS)
+    if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
+      goto invalid_track;
+
+  return TRUE;
+
+invalid_track:
+  {
+    GST_WARNING_OBJECT (piffdemux, "invalid track fragment header");
+    return FALSE;
+  }
+}
+
+static gboolean
+piffdemux_parse_tfxd (GstPiffDemux * piffdemux, PiffDemuxStream *stream,GstByteReader * tfxd)
+{
+  guint8 version = 0;
+
+  // 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
+
+  if (!gst_byte_reader_get_uint8 (tfxd, &version))
+    goto invalid_tfxd;
+
+  if (!gst_byte_reader_skip (tfxd, 3))
+    goto invalid_tfxd;
+
+  if (!piffdemux->lookahead_cnt) {
+    piffdemux->param = (piff_live_param_t *)malloc (sizeof (piff_live_param_t));
+    if (NULL == piffdemux->param) {
+      GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");
+      return FALSE;
+    }
+    piffdemux->param->count = 1;
+    piffdemux->param->long_info = NULL;
+    piffdemux->param->info = NULL;
+    piffdemux->param->is_eos = FALSE;
+
+    // TODO: presentation will be ended based on timeout in souphttpsrc in lookaheadcnt = 0 case
+  }
+
+  if (version == 1) {
+    guint64 duration = 0;
+    guint64 timestamp = 0;
+
+    GST_LOG_OBJECT (piffdemux, "Time and Duration are in 64-bit format...");
+    if (!gst_byte_reader_get_uint64_be (tfxd, &timestamp))
+      goto invalid_tfxd;
+    if (!gst_byte_reader_get_uint64_be (tfxd, &duration))
+      goto invalid_tfxd;
+
+    GST_DEBUG_OBJECT (piffdemux, "tfxd : absolute timestamp = %"G_GUINT64_FORMAT" and duration of fragment = %"G_GUINT64_FORMAT,
+        timestamp, duration);
+
+    if (!piffdemux->lookahead_cnt) {
+      piffdemux->param->long_info = (piff_fragment_longtime_info *)malloc (piffdemux->param->count * sizeof (piff_fragment_longtime_info));
+      if (NULL == piffdemux->param->long_info) {
+        GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");
+        return FALSE;
+      }
+
+      /* Calculate next fragment's timestamp using current fragment's timestamp + duration */
+      piffdemux->param->long_info->duration = GST_CLOCK_TIME_NONE;
+      piffdemux->param->long_info->ts = timestamp +duration;
+    }
+  } else if (version == 0) {
+    guint32 duration = 0;
+    guint32 timestamp = 0;
+    GST_LOG_OBJECT (piffdemux, "Time and Duration are in 32-bit format...");
+
+    if (!gst_byte_reader_get_uint32_be (tfxd, &timestamp))
+      goto invalid_tfxd;
+
+    if (!gst_byte_reader_get_uint32_be (tfxd, &duration))
+      goto invalid_tfxd;
+
+    GST_DEBUG_OBJECT (piffdemux, "tfxd : absolute timestamp = %"G_GUINT32_FORMAT" and duration of fragment = %"G_GUINT32_FORMAT,
+        timestamp, duration);
+
+    if (!piffdemux->lookahead_cnt) {
+      piffdemux->param->info = (piff_fragment_time_info *)malloc (piffdemux->param->count * sizeof (piff_fragment_time_info));
+      if (NULL == piffdemux->param->info) {
+        GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");
+        return FALSE;
+      }
+      /* Calculate next fragment's timestamp using current fragment's timestamp + duration */
+      piffdemux->param->info->duration = GST_CLOCK_TIME_NONE;
+      piffdemux->param->info->ts = timestamp +duration;
+    }
+  } else {
+    GST_ERROR_OBJECT (piffdemux, "Invalid Version in tfxd...");
+    return FALSE;
+  }
+
+  if (!piffdemux->lookahead_cnt) {
+    GST_DEBUG_OBJECT (piffdemux, "Emitting live-param signal...");
+    g_signal_emit (piffdemux, gst_piffdemux_signals[SIGNAL_LIVE_PARAM], 0, piffdemux->param);
+  }
+
+  return TRUE;
+
+invalid_tfxd:
+  GST_ERROR ("Invalid TFXD atom...");
+  return FALSE;
+}
+
+
+static gboolean
+piffdemux_parse_tfrf (GstPiffDemux * piffdemux, PiffDemuxStream *stream,GstByteReader * tfrf)
+{
+  guint8 version = 0;
+  guint8 frag_cnt = 0;
+  guint8 i = 0;
+
+  /* Getting version info */
+  if (!gst_byte_reader_get_uint8 (tfrf, &version))
+    goto invalid_tfrf;
+
+  /* skipping reserved flags */
+  if (!gst_byte_reader_skip (tfrf, 3))
+    goto invalid_tfrf;
+
+  if (!gst_byte_reader_get_uint8 (tfrf, &frag_cnt))
+    goto invalid_tfrf;
+
+  GST_INFO_OBJECT (piffdemux, "Subsequent fragments info count = %d", frag_cnt);
+
+  piffdemux->param = (piff_live_param_t *)malloc(sizeof (piff_live_param_t));
+  if (NULL == piffdemux->param) {
+    GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");
+    return FALSE;
+  }
+
+  piffdemux->param->count = frag_cnt;
+  piffdemux->param->long_info = NULL;
+  piffdemux->param->info = NULL;
+  piffdemux->param->is_eos = FALSE;
+
+  // TODO: Duration and timestamp values need to be posted to msl using g_signal_emit
+
+  if (version == 1) {
+    guint64 duration = 0;
+    guint64 timestamp = 0;
+    GST_LOG_OBJECT (piffdemux, "Time and Duration are in 64-bit format...");
+
+    piffdemux->param->long_info = (piff_fragment_longtime_info *)malloc (piffdemux->param->count * sizeof (piff_fragment_longtime_info));
+    if (NULL == piffdemux->param->long_info) {
+      GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");
+      return FALSE;
+    }
+
+    for (i = 0; i < frag_cnt; i++) {
+      if (!gst_byte_reader_get_uint64_be (tfrf, &timestamp))
+        goto invalid_tfrf;
+      if (!gst_byte_reader_get_uint64_be (tfrf, &duration))
+        goto invalid_tfrf;
+      GST_DEBUG_OBJECT (piffdemux, "tfrf long: absolute timestamp = %"G_GUINT64_FORMAT" and duration of fragment = %"G_GUINT64_FORMAT"\n",
+          timestamp, duration);
+      (piffdemux->param->long_info[i]).ts = timestamp;
+      (piffdemux->param->long_info[i]).duration = duration;
+    }
+  } else if (version == 0) {
+    guint32 duration = 0;
+    guint32 timestamp = 0;
+    GST_LOG_OBJECT (piffdemux, "Time and Duration are in 32-bit format...");
+
+    piffdemux->param->info = (piff_fragment_time_info *)malloc (piffdemux->param->count * sizeof (piff_fragment_time_info));
+    if (NULL == piffdemux->param->info) {
+      GST_ERROR ("Memory not available...\n");
+      return FALSE;
+    }
+
+    for (i = 0; i < frag_cnt; i++) {
+      if (!gst_byte_reader_get_uint32_be (tfrf, &timestamp))
+        goto invalid_tfrf;
+      if (!gst_byte_reader_get_uint32_be (tfrf, &duration))
+        goto invalid_tfrf;
+
+      GST_DEBUG_OBJECT (piffdemux, "tfrf int: absolute timestamp = %"G_GUINT32_FORMAT" and duration of fragment = %"G_GUINT32_FORMAT,
+          timestamp, duration);
+      (piffdemux->param->info[i]).ts = timestamp;
+      (piffdemux->param->info[i]).duration = duration;
+    }
+  } else {
+    GST_ERROR_OBJECT (piffdemux, "Invalid Version in tfrf...");
+    return FALSE;
+  }
+
+  g_print ("Signalling from TFRF box..\n");
+  g_signal_emit (piffdemux, gst_piffdemux_signals[SIGNAL_LIVE_PARAM], 0, piffdemux->param);
+
+  return TRUE;
+
+invalid_tfrf:
+  GST_ERROR_OBJECT (piffdemux, "Invalid TFRF atom...");
+  return FALSE;
+}
+
+
+static gboolean
+piffdemux_parse_moof (GstPiffDemux * piffdemux, const guint8 * buffer, guint length,
+    guint64 moof_offset, PiffDemuxStream * stream)
+{
+  GNode *moof_node, *mfhd_node, *traf_node, *tfhd_node, *trun_node, *uuid_node;
+  GstByteReader mfhd_data, trun_data, tfhd_data, uuid_data;
+  guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
+  gint64 base_offset, running_offset;
+  gint64 uuid_offset = 0;
+  gboolean found_tfxd = FALSE;
+  gboolean found_tfrf = FALSE;
+
+  /* NOTE @stream ignored */
+
+  moof_node = g_node_new ((guint8 *) buffer);
+  piffdemux_parse_node (piffdemux, moof_node, buffer, length);
+  //piffdemux_node_dump (piffdemux, moof_node);
+
+  /* unknown base_offset to start with */
+  base_offset = running_offset = -1;
+
+  mfhd_node = piffdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
+  if (!mfhd_node)
+    goto missing_mfhd;
+
+  if (!piffdemux_parse_mfhd (piffdemux, &mfhd_data))
+    goto missing_mfhd;
+
+  traf_node = piffdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
+  while (traf_node) {
+    /* Fragment Header node */
+    tfhd_node =
+        piffdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
+        &tfhd_data);
+    if (!tfhd_node)
+      goto missing_tfhd;
+    if (!piffdemux_parse_tfhd (piffdemux, &tfhd_data, &ds_duration,
+            &ds_size, &ds_flags, &base_offset))
+      goto missing_tfhd;
+
+    if (G_UNLIKELY (base_offset < -1))
+      goto lost_offset;
+
+    /* Track Run node */
+    trun_node =
+        piffdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
+        &trun_data);
+    while (trun_node) {
+      piffdemux_parse_trun (piffdemux, &trun_data, stream,
+          ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
+          &running_offset);
+      /* iterate all siblings */
+      trun_node = piffdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
+          &trun_data);
+    }
+
+    uuid_node =  piffdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
+    while (uuid_node) {
+      uuid_type_t uuid_type;
+      guint8 *lbuffer = (guint8 *) uuid_node->data;
+
+      gst_byte_reader_init (&uuid_data, lbuffer, PIFF_UINT32 (lbuffer));
+
+      uuid_type = piffdemux_get_uuid_type (piffdemux, &uuid_data, &uuid_offset);
+
+      if ((UUID_TFXD == uuid_type) && piffdemux->is_live) {
+        // TODO: Dont know, why we should not consider tfxd offset...if we use tfxd offset also, not working.. PIFF doc does not say anything :(
+        found_tfxd = TRUE;
+        if (!piffdemux_parse_tfxd (piffdemux, stream, &uuid_data))
+          goto fail;
+      } else if ((UUID_TFRF == uuid_type) && piffdemux->is_live && piffdemux->lookahead_cnt) {
+        found_tfrf = TRUE;
+        if (!piffdemux_parse_tfrf (piffdemux, stream, &uuid_data))
+          goto fail;
+        piffdemux_update_sample_offset (piffdemux, stream, uuid_offset);
+        running_offset += uuid_offset;
+      } else if (UUID_SAMPLE_ENCRYPT == uuid_type) {
+        if (!piffdemux_parse_sample_encryption (piffdemux, &uuid_data, stream))
+          goto fail;
+      } else {
+        GST_WARNING_OBJECT (piffdemux, "Ignoring Wrong UUID...");
+      }
+
+      /* iterate all siblings */
+      uuid_node = piffdemux_tree_get_sibling_by_type (uuid_node, FOURCC_uuid);
+    }
+
+    if (piffdemux->is_live) {
+      if (!found_tfxd) {
+        GST_ERROR_OBJECT (piffdemux, "TFXD box is not present for live stream");
+        goto fail;
+      }
+
+      if (!found_tfrf && piffdemux->lookahead_cnt) {
+        /* when lookahead count is non-zero in manifest & if tfrf box is not present., means EOS */
+        GST_INFO_OBJECT (piffdemux, "Reached Endof Live presentation..");
+
+        piffdemux->param = (piff_live_param_t *)malloc (sizeof (piff_live_param_t));
+        if (NULL == piffdemux->param) {
+          GST_ERROR_OBJECT (piffdemux, "Memory not available...\n");
+          goto fail;
+        }
+        piffdemux->param->count = 0;
+        piffdemux->param->long_info = NULL;
+        piffdemux->param->info = NULL;
+        piffdemux->param->is_eos = TRUE; /* marking EOS */
+        g_signal_emit (piffdemux, gst_piffdemux_signals[SIGNAL_LIVE_PARAM], 0, piffdemux->param);
+      }
+    }
+
+    /* if no new base_offset provided for next traf,
+     * base is end of current traf */
+    base_offset = running_offset;
+    running_offset = -1;
+
+    /* iterate all siblings */
+    traf_node = piffdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
+  }
+  g_node_destroy (moof_node);
+  return TRUE;
+
+missing_mfhd:
+  {
+    GST_DEBUG_OBJECT (piffdemux, "missing mfhd box");
+    goto fail;
+  }
+
+missing_tfhd:
+  {
+    GST_DEBUG_OBJECT (piffdemux, "missing tfhd box");
+    goto fail;
+  }
+lost_offset:
+  {
+    GST_DEBUG_OBJECT (piffdemux, "lost offset");
+    goto fail;
+  }
+fail:
+  {
+    g_node_destroy (moof_node);
+
+    GST_ELEMENT_ERROR (piffdemux, STREAM, DEMUX,
+        ("This file is corrupt and cannot be played."), (NULL));
+
+    return FALSE;
+  }
+}
+
+
+/* activate the given segment number @seg_idx of @stream at time @offset.
+ * @offset is an absolute global position over all the segments.
+ *
+ * This will push out a NEWSEGMENT event with the right values and
+ * position the stream index to the first decodable sample before
+ * @offset.
+ */
+static gboolean
+gst_piffdemux_activate_segment (GstPiffDemux * piffdemux, PiffDemuxStream * stream,
+    guint32 seg_idx, guint64 offset)
+{
+  GstEvent *event;
+  PiffDemuxSegment *segment;
+  guint64 seg_time;
+  guint64 start, stop, time;
+  gdouble rate;
+
+  GST_LOG_OBJECT (piffdemux, "activate segment %d, offset %" G_GUINT64_FORMAT,
+      seg_idx, offset);
+
+  /* update the current segment */
+  stream->segment_index = seg_idx;
+
+  /* get the segment */
+  segment = &stream->segments[seg_idx];
+
+  if (G_UNLIKELY (offset < segment->time)) {
+    GST_WARNING_OBJECT (piffdemux, "offset < segment->time %" G_GUINT64_FORMAT,
+        segment->time);
+    return FALSE;
+  }
+
+  /* segment lies beyond total indicated duration */
+  if (G_UNLIKELY (piffdemux->segment.duration != -1 &&
+          segment->time > piffdemux->segment.duration)) {
+    GST_WARNING_OBJECT (piffdemux, "file duration %" G_GINT64_FORMAT
+        " < segment->time %" G_GUINT64_FORMAT, piffdemux->segment.duration,
+        segment->time);
+    return FALSE;
+  }
+
+  /* get time in this segment */
+  seg_time = offset - segment->time;
+
+  GST_LOG_OBJECT (piffdemux, "seg_time %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (seg_time));
+
+  if (G_UNLIKELY (seg_time > segment->duration)) {
+    GST_LOG_OBJECT (piffdemux, "seg_time > segment->duration %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (segment->duration));
+    return FALSE;
+  }
+
+  /* piffdemux->segment.stop is in outside-time-realm, whereas
+   * segment->media_stop is in track-time-realm.
+   *
+   * In order to compare the two, we need to bring segment.stop
+   * into the track-time-realm */
+
+  stop = piffdemux->segment.stop;
+  if (stop == -1)
+    stop = piffdemux->segment.duration;
+  if (stop == -1)
+    stop = segment->media_stop;
+  else
+    stop =
+        MIN (segment->media_stop, stop - segment->time + segment->media_start);
+
+  if (piffdemux->segment.rate >= 0) {
+    start = MIN (segment->media_start + seg_time, stop);
+    time = offset;
+  } else {
+    if (segment->media_start >= piffdemux->segment.start) {
+      start = segment->media_start;
+      time = segment->time;
+    } else {
+      start = piffdemux->segment.start;
+      time = segment->time + (piffdemux->segment.start - segment->media_start);
+    }
+
+    start = MAX (segment->media_start, piffdemux->segment.start);
+    stop = MIN (segment->media_start + seg_time, stop);
+  }
+
+  GST_DEBUG_OBJECT (piffdemux, "newsegment %d from %" GST_TIME_FORMAT
+      " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
+      GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
+
+  /* combine global rate with that of the segment */
+  rate = segment->rate * piffdemux->segment.rate;
+
+  /* update the segment values used for clipping */
+  gst_segment_init (&stream->segment, GST_FORMAT_TIME);
+  gst_segment_set_newsegment (&stream->segment, FALSE, rate, GST_FORMAT_TIME,
+      start, stop, time);
+
+  /* now prepare and send the segment */
+  event = gst_event_new_new_segment (FALSE, rate, GST_FORMAT_TIME,
+      start, stop, time);
+  gst_pad_push_event (piffdemux->srcpad, event);
+  /* assume we can send more data now */
+  stream->last_ret = GST_FLOW_OK;
+  /* clear to send tags on this pad now */
+  gst_piffdemux_push_tags (piffdemux, stream);
+
+  return TRUE;
+}
+
+
+/* prepare to get the current sample of @stream, getting essential values.
+ *
+ * This function will also prepare and send the segment when needed.
+ *
+ * Return FALSE if the stream is EOS.
+ */
+static gboolean
+gst_piffdemux_prepare_current_sample (GstPiffDemux * piffdemux,
+    PiffDemuxStream * stream, guint64 * offset, guint * size, guint64 * timestamp,
+    guint64 * duration, gboolean * keyframe)
+{
+  PiffDemuxSample *sample;
+  guint64 time_position;
+  guint32 seg_idx;
+
+  g_return_val_if_fail (stream != NULL, FALSE);
+
+  time_position = stream->time_position;
+  if (G_UNLIKELY (time_position == -1))
+    goto eos;
+
+  seg_idx = stream->segment_index;
+  if (G_UNLIKELY (seg_idx == -1)) {
+    /* find segment corresponding to time_position if we are looking
+     * for a segment. */
+    seg_idx = gst_piffdemux_find_segment (piffdemux, stream, time_position);
+
+    /* nothing found, we're really eos */
+    if (seg_idx == -1)
+      goto eos;
+  }
+
+  /* different segment, activate it, sample_index will be set. */
+  if (G_UNLIKELY (stream->segment_index != seg_idx))
+    gst_piffdemux_activate_segment (piffdemux, stream, seg_idx, time_position);
+
+  GST_LOG_OBJECT (piffdemux, "segment active, index = %u of %u",
+      stream->sample_index, stream->n_samples);
+
+  if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
+    goto eos;
+
+
+  /* now get the info for the sample we're at */
+  sample = &stream->samples[stream->sample_index];
+
+  *timestamp = PIFFSAMPLE_PTS (stream, sample);
+  *offset = sample->offset;
+  *size = sample->size;
+  *duration = PIFFSAMPLE_DUR_PTS (stream, sample, *timestamp);
+  *keyframe = PIFFSAMPLE_KEYFRAME (stream, sample);
+
+  return TRUE;
+
+  /* special cases */
+eos:
+  {
+    stream->time_position = -1;
+    return FALSE;
+  }
+}
+
+/* the input buffer metadata must be writable,
+ * but time/duration etc not yet set and need not be preserved */
+static GstBuffer *
+gst_piffdemux_process_buffer (GstPiffDemux * piffdemux, PiffDemuxStream * stream,
+    GstBuffer * buf)
+{
+  guint8 *data;
+  guint size, nsize = 0;
+  gchar *str;
+
+  data = GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
+
+  if (G_UNLIKELY (stream->subtype != FOURCC_text)) {
+    return buf;
+  }
+
+  if (G_LIKELY (size >= 2)) {
+    nsize = GST_READ_UINT16_BE (data);
+    nsize = MIN (nsize, size - 2);
+  }
+
+  GST_LOG_OBJECT (piffdemux, "3GPP timed text subtitle: %d/%d", nsize, size);
+
+  /* takes care of UTF-8 validation or UTF-16 recognition,
+   * no other encoding expected */
+  str = gst_tag_freeform_string_to_utf8 ((gchar *) data + 2, nsize, NULL);
+  if (str) {
+    gst_buffer_unref (buf);
+    buf = gst_buffer_new ();
+    GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = (guint8 *) str;
+    GST_BUFFER_SIZE (buf) = strlen (str);
+  } else {
+    /* may be 0-size subtitle, which is also sent to keep pipeline going */
+    GST_BUFFER_DATA (buf) = data + 2;
+    GST_BUFFER_SIZE (buf) = nsize;
+  }
+
+  /* FIXME ? convert optional subsequent style info to markup */
+
+  return buf;
+}
+
+/* Sets a buffer's attributes properly and pushes it downstream.
+ * Also checks for additional actions and custom processing that may
+ * need to be done first.
+ */
+static gboolean
+gst_piffdemux_decorate_and_push_buffer (GstPiffDemux * piffdemux,
+    PiffDemuxStream * stream, GstBuffer * buf,
+    guint64 timestamp, guint64 duration, gboolean keyframe, guint64 position,
+    guint64 byte_position)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  if (!stream->caps) {
+    GST_WARNING_OBJECT (piffdemux, "caps are empty...creat any caps");
+    stream->caps = gst_caps_new_any();
+    if (!stream->caps) {
+      GST_ERROR_OBJECT (piffdemux, "failed to create caps...");
+      ret = GST_FLOW_ERROR;
+      goto exit;
+    }
+  }
+
+  /* position reporting */
+  if (piffdemux->segment.rate >= 0) {
+   // TODO: Segment fault is coming here for Audio stream.. need to check
+
+    gst_segment_set_last_stop (&piffdemux->segment, GST_FORMAT_TIME, position);
+    //gst_piffdemux_sync_streams (piffdemux);
+  }
+
+  /* send out pending buffers */
+  while (stream->buffers) {
+    GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
+
+    if (G_UNLIKELY (stream->discont)) {
+      GST_LOG_OBJECT (piffdemux, "marking discont buffer");
+      GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
+      stream->discont = FALSE;
+    }
+    gst_buffer_set_caps (buffer, stream->caps);
+
+    gst_pad_push (piffdemux->srcpad, buffer);
+
+    stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
+  }
+
+  /* we're going to modify the metadata */
+  buf = gst_buffer_make_metadata_writable (buf);
+
+  /* for subtitle processing */
+  if (G_UNLIKELY (stream->need_process))
+    buf = gst_piffdemux_process_buffer (piffdemux, stream, buf);
+
+  GST_BUFFER_TIMESTAMP (buf) = timestamp;
+  GST_BUFFER_DURATION (buf) = duration;
+  GST_BUFFER_OFFSET (buf) = -1;
+  GST_BUFFER_OFFSET_END (buf) = -1;
+
+  if (G_UNLIKELY (stream->padding)) {
+    GST_BUFFER_DATA (buf) += stream->padding;
+    GST_BUFFER_SIZE (buf) -= stream->padding;
+  }
+
+  if (G_UNLIKELY (buf == NULL))
+    goto exit;
+
+  if (G_UNLIKELY (stream->discont)) {
+    GST_LOG_OBJECT (piffdemux, "marking discont buffer");
+    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+    stream->discont = FALSE;
+  }
+
+  if (!keyframe)
+    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+
+ //g_print ("\n\npad caps : %s\n\n", gst_caps_to_string (gst_pad_get_caps (stream->pad)));
+
+  //gst_buffer_set_caps (buf, stream->caps); // commenting to avoid caps by setting properties
+
+  // TODO: need to see how resolution switch will work
+  gst_buffer_set_caps (buf, stream->caps);
+
+#ifdef DRM_ENABLE
+  if (piffdemux->encrypt_content) {
+    drm_trusted_payload_info_s read_input_data = {0, };
+    drm_trusted_read_decrypt_resp_data_s read_output_data = {0, };
+    gint offset = 0;
+    PiffDemuxSample *sample = &stream->samples[stream->sample_index];
+
+    if (sample->sub_encry) {
+      offset = sample->sub_encry->sub_entry[0].LenofClearData;
+    }
+
+    read_input_data.media_offset = 0;
+    read_input_data.payload_data =  GST_BUFFER_DATA(buf) + offset;
+    read_input_data.payload_data_len = GST_BUFFER_SIZE(buf) - offset;
+    read_input_data.payload_iv_len = 8;
+    read_input_data.payload_iv = (unsigned char *) malloc (8);
+    read_input_data.payload_data_output =  GST_BUFFER_DATA(buf) + offset;
+    if (NULL == read_input_data.payload_iv) {
+      GST_ERROR ("Failed to allocate memory...");
+      ret = GST_FLOW_ERROR;
+      goto exit;
+    }
+    memcpy (read_input_data.payload_iv, sample->iv, 8);
+
+    ret = drm_trusted_read_decrypt_session(piffdemux->pr_handle , &read_input_data, &read_output_data);
+    if (DRM_TRUSTED_RETURN_SUCCESS != ret) {
+      GST_ERROR_OBJECT (piffdemux, "failed to decrypt buffer...");
+      free (read_input_data.payload_iv);
+      ret = GST_FLOW_ERROR;
+      goto exit;
+    }
+
+    if (read_output_data.read_size != read_input_data.payload_data_len) {
+      g_print ("Decrypter did not consume data fully...\n\n\n");
+    }
+
+    free (read_input_data.payload_iv);
+    read_input_data.payload_iv = NULL;
+
+  }
+#endif
+
+  GST_LOG_OBJECT (piffdemux,
+      "Pushing buffer of size = %d with time %" GST_TIME_FORMAT ", duration %"
+      GST_TIME_FORMAT, GST_BUFFER_SIZE(buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
+
+#ifdef DEC_OUT_FRAME_DUMP
+    {
+        int written = 0;
+        written = fwrite (GST_BUFFER_DATA (buf), sizeof (unsigned char), GST_BUFFER_SIZE (buf), piffdump);
+        g_print ("PIFFDEMUX: written = %d\n", written);
+        fflush (piffdump);
+    }
+#endif
+
+  ret = gst_pad_push (piffdemux->srcpad, buf);
+
+exit:
+  return ret;
+}
+
+
+/*
+ * next_entry_size
+ *
+ * Returns the size of the first entry at the current offset.
+ * If -1, there are none (which means EOS or empty file).
+ */
+static guint64
+next_entry_size (GstPiffDemux * demux)
+{
+  PiffDemuxStream *stream = demux->stream;
+  PiffDemuxSample *sample;
+
+  GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
+      demux->offset);
+
+  GST_DEBUG_OBJECT (demux, "demux->sample_index = %d", stream->sample_index);
+
+  if (stream->sample_index == -1)
+    stream->sample_index = 0;
+
+  if (stream->sample_index >= stream->n_samples) {
+    GST_LOG_OBJECT (demux, "stream %d samples exhausted n_samples = %d",
+               stream->sample_index, stream->n_samples);
+    return -1;
+  }
+
+  sample = &stream->samples[stream->sample_index];
+
+  GST_LOG_OBJECT (demux,
+      "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
+      " / size:%" G_GUINT32_FORMAT ")", stream->sample_index, stream->sample_index,
+      sample->offset, sample->size);
+
+  GST_LOG_OBJECT (demux, "stream : demux->offset :%"G_GUINT64_FORMAT, demux->offset);
+
+  stream = demux->stream;
+  sample = &stream->samples[stream->sample_index];
+
+  if (sample->offset >= demux->offset) {
+    demux->todrop = sample->offset - demux->offset;
+    return sample->size + demux->todrop;
+  }
+
+  GST_DEBUG_OBJECT (demux,
+      "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
+  return -1;
+}
+
+static void
+gst_piffdemux_post_progress (GstPiffDemux * demux, gint num, gint denom)
+{
+  gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
+
+  gst_element_post_message (GST_ELEMENT_CAST (demux),
+      gst_message_new_element (GST_OBJECT_CAST (demux),
+          gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
+}
+
+static gboolean
+piffdemux_seek_offset (GstPiffDemux * demux, guint64 offset)
+{
+  GstEvent *event;
+  gboolean res = 0;
+
+  GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
+
+  event =
+      gst_event_new_seek (1.0, GST_FORMAT_BYTES,
+      GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
+      GST_SEEK_TYPE_NONE, -1);
+
+  res = gst_pad_push_event (demux->sinkpad, event);
+
+  return res;
+}
+
+static GstFlowReturn
+gst_piffdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
+{
+  GstPiffDemux *demux;
+  GstFlowReturn ret = GST_FLOW_OK;
+  demux = GST_PIFFDEMUX (gst_pad_get_parent (sinkpad));
+#ifdef DRM_ENABLE
+  if (demux->encrypt_content && !demux->decrypt_init) {
+    int ret = -1;
+    drm_trusted_permission_type_e perm_type = DRM_TRUSTED_PERMISSION_TYPE_PLAY;
+    drm_trusted_open_decrypt_info_s open_input_data = {0, };
+    drm_trusted_open_decrypt_resp_data_s open_output_data = {0, };
+    drm_trusted_set_consumption_state_info_s state_input_data = {0, };
+
+    open_input_data.file_type = DRM_TRUSTED_TYPE_PIFF;
+    open_input_data.permission = perm_type;
+    open_input_data.operation_callback.callback = test_drm_trusted_operation_cb;
+    open_input_data.lic_header.header = GST_BUFFER_DATA(demux->protection_header);
+    open_input_data.lic_header.header_len = GST_BUFFER_SIZE (demux->protection_header);
+
+    /* Open Decrypt Session*/
+    ret = drm_trusted_open_decrypt_session(&open_input_data, &open_output_data, &(demux->pr_handle));
+    if (DRM_TRUSTED_RETURN_SUCCESS != ret) {
+      GST_ERROR_OBJECT (demux, "failed to open decrypt session");
+      goto unknown_stream;
+    }
+
+    /* Before Read, Appropriate state MUST be SET */
+    state_input_data.state = DRM_CONSUMPTION_STARTED;
+    ret = drm_trusted_set_decrypt_state(demux->pr_handle, &state_input_data);
+    if (DRM_TRUSTED_RETURN_SUCCESS != ret) {
+      GST_ERROR_OBJECT (demux, "failed to set decrypt state...");
+      goto unknown_stream;
+    }
+
+    demux->decrypt_init = TRUE;
+  }
+#endif
+  gst_adapter_push (demux->adapter, inbuf);
+
+  /* we never really mean to buffer that much */
+  if (demux->neededbytes == -1)
+    goto eos;
+
+  GST_DEBUG_OBJECT (demux, "pushing in inbuf %p, neededbytes:%u, available:%u",
+      inbuf, demux->neededbytes, gst_adapter_available (demux->adapter));
+
+  while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
+      (ret == GST_FLOW_OK)) {
+
+    GST_DEBUG_OBJECT (demux,
+        "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
+        demux->state, demux->neededbytes, demux->offset);
+
+    switch (demux->state) {
+      case PIFFDEMUX_STATE_INITIAL:{
+        const guint8 *data;
+        guint32 fourcc;
+        guint64 size;
+
+        data = gst_adapter_peek (demux->adapter, demux->neededbytes);
+
+        if (!data) {
+          GST_ERROR_OBJECT (demux, "peeked adapter buffer is NULL");
+          ret = GST_FLOW_ERROR;
+          break;
+        }
+
+        /* get fourcc/length, set neededbytes */
+        extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
+            &size, &fourcc);
+        GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
+            "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
+        if (size == 0) {
+          GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
+              ("This file is invalid and cannot be played."),
+              ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
+                  GST_FOURCC_ARGS (fourcc)));
+
+          ret = GST_FLOW_ERROR;
+          break;
+        }
+
+        if (fourcc == FOURCC_mdat) {
+          if (demux->moof_rcvd) {
+            /* we have the headers, start playback */
+            demux->state = PIFFDEMUX_STATE_MOVIE;
+            demux->neededbytes = next_entry_size (demux);
+            demux->mdatleft = size;
+
+            /* Only post, event on pads is done after newsegment */
+            piffdemux_post_global_tags (demux);
+          } else {
+             GST_ERROR_OBJECT (demux, "mdata received before moof.. not handled");
+             goto unknown_stream;
+          }
+        } else if (G_UNLIKELY (size > PIFFDEMUX_MAX_ATOM_SIZE)) {
+          GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
+              ("This file is invalid and cannot be played."),
+              ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
+                  GST_FOURCC_ARGS (fourcc), size));
+          ret = GST_FLOW_ERROR;
+          break;
+        } else {
+          demux->neededbytes = size;
+          demux->state = PIFFDEMUX_STATE_HEADER;
+        }
+        break;
+      }
+      case PIFFDEMUX_STATE_HEADER:{
+        const guint8 *data;
+        guint32 fourcc;
+
+        GST_DEBUG_OBJECT (demux, "In header");
+
+        data = gst_adapter_peek (demux->adapter, demux->neededbytes);
+
+        if (!data) {
+          GST_ERROR_OBJECT (demux, "peeked adapter buffer is NULL");
+          ret = GST_FLOW_ERROR;
+          break;
+        }
+
+        /* parse the header */
+        extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
+            &fourcc);
+        if (fourcc == FOURCC_moof) {
+            GST_DEBUG_OBJECT (demux, "Parsing [moof]");
+            if (!piffdemux_parse_moof (demux, data, demux->neededbytes,
+                    demux->offset, demux->stream)) {
+              ret = GST_FLOW_ERROR;
+              goto done;
+            }
+            demux->moof_rcvd = TRUE;
+        }  else {
+          GST_WARNING_OBJECT (demux,
+              "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
+              GST_FOURCC_ARGS (fourcc));
+          /* Let's jump that one and go back to initial state */
+        }
+
+        if (demux->mdatbuffer) {
+          /* the mdat was before the header */
+          GST_DEBUG_OBJECT (demux, "We have mdatbuffer:%p",
+             demux->mdatbuffer);
+          gst_adapter_clear (demux->adapter);
+          demux->mdatbuffer = NULL;
+          demux->offset = demux->mdatoffset;
+          demux->neededbytes = next_entry_size (demux);
+          demux->state = PIFFDEMUX_STATE_MOVIE;
+          demux->mdatleft = gst_adapter_available (demux->adapter);
+
+          /* Only post, event on pads is done after newsegment */
+          piffdemux_post_global_tags (demux);
+        } else {
+          GST_DEBUG_OBJECT (demux, "Carrying on normally");
+          gst_adapter_flush (demux->adapter, demux->neededbytes);
+            demux->offset += demux->neededbytes;
+          demux->neededbytes = 16;
+          demux->state = PIFFDEMUX_STATE_INITIAL;
+        }
+
+        break;
+      }
+      case PIFFDEMUX_STATE_BUFFER_MDAT:{
+        GstBuffer *buf;
+
+        GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
+            demux->offset);
+        buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
+        GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
+            GST_FOURCC_ARGS (PIFF_FOURCC (GST_BUFFER_DATA (buf) + 4)));
+        if (demux->mdatbuffer)
+          demux->mdatbuffer = gst_buffer_join (demux->mdatbuffer, buf);
+        else
+          demux->mdatbuffer = buf;
+        demux->offset += demux->neededbytes;
+        demux->neededbytes = 16;
+        demux->state = PIFFDEMUX_STATE_INITIAL;
+        gst_piffdemux_post_progress (demux, 1, 1);
+
+        break;
+      }
+      case PIFFDEMUX_STATE_MOVIE:{
+        GstBuffer *outbuf;
+        PiffDemuxStream *stream = demux->stream;
+        PiffDemuxSample *sample;
+        guint64 timestamp, duration, position;
+        gboolean keyframe;
+
+        GST_DEBUG_OBJECT (demux,
+            "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
+
+        if (demux->fragmented) {
+          GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
+              demux->mdatleft);
+          if (G_LIKELY (demux->todrop < demux->mdatleft)) {
+            /* if needed data starts within this atom,
+             * then it should not exceed this atom */
+            if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
+
+              GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
+                  ("This file is invalid and cannot be played."),
+                  ("sample data crosses atom boundary"));
+
+              ret = GST_FLOW_ERROR;
+              break;
+            }
+            demux->mdatleft -= demux->neededbytes;
+          } else {
+            GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
+            /* so we are dropping more than left in this atom */
+            demux->todrop -= demux->mdatleft;
+            demux->neededbytes -= demux->mdatleft;
+            demux->mdatleft = 0;
+            /* need to resume atom parsing so we do not miss any other pieces */
+            demux->state = PIFFDEMUX_STATE_INITIAL;
+            demux->neededbytes = 16;
+            break;
+          }
+        }
+
+        if (demux->todrop) {
+          GST_LOG_OBJECT (demux, "Dropping %d bytes", demux->todrop);
+          gst_adapter_flush (demux->adapter, demux->todrop);
+          demux->neededbytes -= demux->todrop;
+          demux->offset += demux->todrop;
+        }
+
+        if ( !stream->sent_nsevent) {
+          //TODO: better to parse sink event function and send that new_segment
+#if 1
+          demux->pending_newsegment = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+                                       demux->stream->start_ts, -1, demux->stream->start_ts);
+#else
+          demux->pending_newsegment = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+                                        0, gst_util_uint64_scale (stream->duration, GST_SECOND, stream->timescale), 0);
+#endif
+
+          GST_INFO_OBJECT (demux, "New segment event : start = %"GST_TIME_FORMAT", stop = %" GST_TIME_FORMAT,
+                            GST_TIME_ARGS (demux->stream->start_ts), GST_TIME_ARGS(gst_util_uint64_scale (stream->duration, GST_SECOND, stream->timescale)));
+
+          if (!gst_pad_push_event (demux->srcpad, demux->pending_newsegment)) {
+            GST_ERROR_OBJECT (demux, "failding to send new segment...");
+            goto newsegment_error;
+          }
+          stream->sent_nsevent = TRUE;
+       }
+
+        /* Put data in a buffer, set timestamps, caps, ... */
+        outbuf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
+
+        GST_DEBUG_OBJECT (demux, "Taken %d size buffer from adapter...", outbuf ? GST_BUFFER_SIZE (outbuf) : 0);
+
+        GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (stream->fourcc));
+
+        g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
+
+        sample = &stream->samples[stream->sample_index];
+
+        GST_DEBUG_OBJECT (demux, "start_ts = %"GST_TIME_FORMAT" ts : %"GST_TIME_FORMAT" ts = %llu, pts_offset = %u, scale = %d\n",
+                       GST_TIME_ARGS(stream->start_ts),GST_TIME_ARGS(sample->timestamp), sample->timestamp,
+                       sample->pts_offset,stream->timescale);
+
+        position = PIFFSAMPLE_DTS (stream, sample);
+        timestamp = PIFFSAMPLE_PTS (stream, sample) + stream->start_ts; // Adding to avoid resetting of timestamp
+        duration = PIFFSAMPLE_DUR_DTS (stream, sample, position);
+        keyframe = PIFFSAMPLE_KEYFRAME (stream, sample);
+
+        ret = gst_piffdemux_decorate_and_push_buffer (demux, stream, outbuf,
+            timestamp, duration, keyframe, position, demux->offset);
+
+        stream->sample_index++;
+
+        /* update current offset and figure out size of next buffer */
+        GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
+            demux->offset, demux->neededbytes);
+        demux->offset += demux->neededbytes;
+        GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
+            demux->offset);
+
+        if ((demux->neededbytes = next_entry_size (demux)) == -1) {
+          GST_DEBUG_OBJECT (demux, "finished parsing mdat, need to search next moof atom");
+          demux->neededbytes = 16;
+          demux->state = PIFFDEMUX_STATE_INITIAL;
+          GST_DEBUG ("\n\n Storing %s last_ts %"GST_TIME_FORMAT"\n\n", stream->subtype == FOURCC_vide ? "video" : "audio", GST_TIME_ARGS(timestamp));
+          stream->start_ts = timestamp + duration;
+          //goto eos;
+        }
+        break;
+      }
+      default:
+        goto invalid_state;
+    }
+  }
+
+  /* when buffering movie data, at least show user something is happening */
+  if (ret == GST_FLOW_OK && demux->state == PIFFDEMUX_STATE_BUFFER_MDAT &&
+      gst_adapter_available (demux->adapter) <= demux->neededbytes) {
+    gst_piffdemux_post_progress (demux, gst_adapter_available (demux->adapter),
+        demux->neededbytes);
+  }
+done:
+  gst_object_unref (demux);
+
+  return ret;
+
+  /* ERRORS */
+unknown_stream:
+  {
+    GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+eos:
+  {
+    GST_DEBUG_OBJECT (demux, "no next entry, EOS");
+    ret = GST_FLOW_UNEXPECTED;
+    goto done;
+  }
+invalid_state:
+  {
+    GST_ELEMENT_ERROR (demux, STREAM, FAILED,
+        (NULL), ("piffdemuxer invalid state %d", demux->state));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+newsegment_error:
+  {
+    GST_ELEMENT_ERROR (demux, STREAM, FAILED,
+        (NULL), ("could not send newsegment event"));
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
+}
+
+static gboolean
+piffdemux_parse_container (GstPiffDemux * piffdemux, GNode * node, const guint8 * buf,
+    const guint8 * end)
+{
+  while (G_UNLIKELY (buf < end)) {
+    GNode *child;
+    guint32 len;
+
+    if (G_UNLIKELY (buf + 4 > end)) {
+      GST_LOG_OBJECT (piffdemux, "buffer overrun");
+      break;
+    }
+    len = PIFF_UINT32 (buf);
+    if (G_UNLIKELY (len == 0)) {
+      GST_LOG_OBJECT (piffdemux, "empty container");
+      break;
+    }
+    if (G_UNLIKELY (len < 8)) {
+      GST_WARNING_OBJECT (piffdemux, "length too short (%d < 8)", len);
+      break;
+    }
+    if (G_UNLIKELY (len > (end - buf))) {
+      GST_WARNING_OBJECT (piffdemux, "length too long (%d > %d)", len,
+          (gint) (end - buf));
+      break;
+    }
+
+    child = g_node_new ((guint8 *) buf);
+    g_node_append (node, child);
+    GST_LOG_OBJECT (piffdemux, "adding new node of len %d", len);
+    piffdemux_parse_node (piffdemux, child, buf, len);
+
+    buf += len;
+  }
+  return TRUE;
+}
+
+
+static gboolean
+piffdemux_parse_node (GstPiffDemux * piffdemux, GNode * node, const guint8 * buffer,
+    guint length)
+{
+  guint32 fourcc = 0;
+  guint32 node_length = 0;
+  const PiffNodeType *type;
+  const guint8 *end;
+
+  GST_LOG_OBJECT (piffdemux, "piffdemux_parse buffer %p length %u", buffer, length);
+
+  if (G_UNLIKELY (length < 8))
+    goto not_enough_data;
+
+  node_length = PIFF_UINT32 (buffer);
+  fourcc = PIFF_FOURCC (buffer + 4);
+
+  /* ignore empty nodes */
+  if (G_UNLIKELY (fourcc == 0 || node_length == 8))
+    return TRUE;
+
+  type = piffdemux_type_get (fourcc);
+
+  end = buffer + length;
+
+  GST_LOG_OBJECT (piffdemux,
+      "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
+      GST_FOURCC_ARGS (fourcc), node_length, type->name);
+
+  if (node_length > length)
+    goto broken_atom_size;
+
+  if (type->flags & PIFF_FLAG_CONTAINER) {
+    piffdemux_parse_container (piffdemux, node, buffer + 8, end);
+  }
+  GST_LOG_OBJECT (piffdemux, "parsed '%" GST_FOURCC_FORMAT "'",
+      GST_FOURCC_ARGS (fourcc));
+  return TRUE;
+
+/* ERRORS */
+not_enough_data:
+  {
+
+    GST_ELEMENT_ERROR (piffdemux, STREAM, DEMUX,
+        ("This file is corrupt and cannot be played."),
+        ("Not enough data for an atom header, got only %u bytes", length));
+
+    return FALSE;
+  }
+broken_atom_size:
+  {
+    GST_ELEMENT_ERROR (piffdemux, STREAM, DEMUX,
+        ("This file is corrupt and cannot be played."),
+        ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
+            "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
+            length));
+
+    return FALSE;
+  }
+}
+
+
+static GNode *
+piffdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
+{
+  GNode *child;
+  guint8 *buffer;
+  guint32 child_fourcc;
+
+  for (child = g_node_first_child (node); child;
+      child = g_node_next_sibling (child)) {
+    buffer = (guint8 *) child->data;
+
+    child_fourcc = PIFF_FOURCC (buffer + 4);
+
+    if (G_UNLIKELY (child_fourcc == fourcc)) {
+      return child;
+    }
+  }
+  return NULL;
+}
+
+static GNode *
+piffdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
+    GstByteReader * parser)
+{
+  GNode *child;
+  guint8 *buffer;
+  guint32 child_fourcc, child_len;
+
+  for (child = g_node_first_child (node); child;
+      child = g_node_next_sibling (child)) {
+    buffer = (guint8 *) child->data;
+
+    child_len = PIFF_UINT32 (buffer);
+    child_fourcc = PIFF_FOURCC (buffer + 4);
+
+    if (G_UNLIKELY (child_fourcc == fourcc)) {
+      if (G_UNLIKELY (child_len < (4 + 4)))
+        return NULL;
+      /* FIXME: must verify if atom length < parent atom length */
+      gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
+      return child;
+    }
+  }
+  return NULL;
+}
+
+static GNode *
+piffdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
+    GstByteReader * parser)
+{
+  GNode *child;
+  guint8 *buffer;
+  guint32 child_fourcc, child_len;
+
+  for (child = g_node_next_sibling (node); child;
+      child = g_node_next_sibling (child)) {
+    buffer = (guint8 *) child->data;
+
+    child_fourcc = PIFF_FOURCC (buffer + 4);
+
+    if (child_fourcc == fourcc) {
+      if (parser) {
+        child_len = PIFF_UINT32 (buffer);
+        if (G_UNLIKELY (child_len < (4 + 4)))
+          return NULL;
+        /* FIXME: must verify if atom length < parent atom length */
+        gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
+      }
+      return child;
+    }
+  }
+  return NULL;
+}
+
+static GNode *
+piffdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
+{
+  return piffdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
+}
+
+#define _codec(name) \
+  do { \
+    if (codec_name) { \
+      *codec_name = g_strdup (name); \
+    } \
+  } while (0)
+
+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)
+{
+  GstCaps *caps = NULL;
+  GstBuffer *dci = NULL;
+
+  if (codec_data && codec_data_len) {
+    dci = gst_buffer_new_and_alloc (codec_data_len);
+    if (!dci) {
+      GST_ERROR_OBJECT (piffdemux, "failed to create codec data buffer...");
+    } else {
+      memcpy (GST_BUFFER_DATA(dci), codec_data, codec_data_len);
+    }
+  }
+
+  switch (fourcc) {
+
+    case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
+      caps = gst_caps_new_simple ("video/x-h264",
+                                  "width", G_TYPE_INT, width,
+                                  "height", G_TYPE_INT, height,
+                                  "framerate", GST_TYPE_FRACTION, fps_n, fps_d,
+                                  "stream-format", G_TYPE_STRING, "avc",
+                                  "alignment", G_TYPE_STRING, "au",
+                                  "codec_data", GST_TYPE_BUFFER, dci,
+                                  NULL);
+      break;
+
+    case FOURCC_ovc1:
+      caps = gst_caps_new_simple ("video/x-wmv",
+                                 "width", G_TYPE_INT, width,
+                                  "height", G_TYPE_INT, height,
+                                  "framerate", GST_TYPE_FRACTION, fps_n, fps_d,
+                                  "wmvversion", G_TYPE_INT, 3,
+                                  "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'),
+                                  "codec_data", GST_TYPE_BUFFER, dci,
+                                  NULL);
+      break;
+
+    default: {
+      char *s;
+      s = g_strdup_printf ("video/x-gst-fourcc-%" GST_FOURCC_FORMAT,
+          GST_FOURCC_ARGS (fourcc));
+      caps = gst_caps_new_simple (s,
+                                  "width", G_TYPE_INT, width,
+                                  "height", G_TYPE_INT, height,
+                                  "framerate", GST_TYPE_FRACTION, fps_n, fps_d,
+                                  "codec_data", GST_TYPE_BUFFER, dci,
+                                  NULL);
+      break;
+    }
+  }
+
+  piffdemux->stream->caps = caps;
+  gchar *caps_string = gst_caps_to_string(caps);
+  GST_INFO_OBJECT (piffdemux, "prepared video caps : %s", caps_string);
+  g_free(caps_string);
+  caps_string = NULL;
+}
+
+void
+gst_piffdemux_set_audio_params (GstPiffDemux * piffdemux, guint fourcc,
+                                       guint sampling_rate, guint bps, guint channels, unsigned char *codec_data, unsigned int codec_data_len)
+{
+  GstCaps *caps = NULL;
+  GstBuffer *dci = NULL;
+
+  if (codec_data && codec_data_len) {
+    dci = gst_buffer_new_and_alloc (codec_data_len);
+    if (!dci) {
+      GST_ERROR_OBJECT (piffdemux, "failed to create codec data buffer...");
+    } else {
+      memcpy (GST_BUFFER_DATA(dci), codec_data, codec_data_len);
+    }
+  }
+
+  switch (fourcc) {
+
+    case GST_MAKE_FOURCC ('m', 'p', '4', 'a'):
+      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) sampling_rate,
+                                  "channels", G_TYPE_INT, channels,
+                                  NULL);
+      break;
+
+    case FOURCC_owma:
+      caps = gst_caps_new_simple ("audio/x-wma",
+                                 "rate", G_TYPE_INT, (int) sampling_rate,
+                                  "channels", G_TYPE_INT, channels,
+                                 NULL);
+      break;
+
+    default: {
+      char *s;
+      s = g_strdup_printf ("audio/x-gst-fourcc-%" GST_FOURCC_FORMAT,
+          GST_FOURCC_ARGS (fourcc));
+      caps = gst_caps_new_simple (s,
+                                 "rate", G_TYPE_INT, (int) sampling_rate,
+                                  "channels", G_TYPE_INT, channels,
+                                  NULL);
+      break;
+    }
+  }
+
+  piffdemux->stream->caps = caps;
+  char *tmp_caps_name = gst_caps_to_string(caps);
+  GST_INFO_OBJECT (piffdemux, "prepared audio caps : %s", tmp_caps_name);
+  g_free(tmp_caps_name);
+
+}
+
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+
+void
+__gst_piffdemux_marshal_BOOLEAN__OBJECT (GClosure *closure,
+                                   GValue       *return_value G_GNUC_UNUSED,
+                                   guint         n_param_values,
+                                   const GValue *param_values,
+                                   gpointer      invocation_hint G_GNUC_UNUSED,
+                                   gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT) (gpointer  data1,
+                                                    gpointer      arg_1,
+                                                    gpointer     data2);
+  register GMarshalFunc_BOOLEAN__OBJECT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+  {
+    data1 = closure->data;
+    data2 = g_value_peek_pointer (param_values + 0);
+  }
+  else
+  {
+    data1 = g_value_peek_pointer (param_values + 0);
+    data2 = closure->data;
+  }
+  callback = (GMarshalFunc_BOOLEAN__OBJECT) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_object (param_values + 1),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+#define PIFFDEMUX_SPSPPS_LENGTH_SIZE     2
+
+static gboolean
+ConvertH264_MetaDCI_to_3GPPDCI(unsigned char *dci_meta_buf, unsigned int dci_meta_size, unsigned char **dci_3gpp_buf, unsigned int *dci_3gpp_size)
+{
+  unsigned short unit_size = 0;
+  unsigned int total_size = 0;
+  unsigned char unit_nb = 0;
+  unsigned char sps_done = 0;
+  const unsigned char *extradata = NULL;
+  unsigned int h264_nal_length_size = 0;
+  unsigned char *out = NULL;
+  //g_print ("\n\nConvertH264_MetaDCI_to_3GPPDCI Entering.............\n");
+
+  /* nothing to filter */
+  if ((dci_meta_buf == NULL) || (dci_meta_size < 6))
+  {
+    GST_ERROR ("Insufficient codec data...\n");
+    return FALSE;
+  }
+
+  /* Removing unnecessary info in meta data */
+  extradata = (unsigned char *)dci_meta_buf + 4;
+
+  /* retrieve Length of Length*/
+  h264_nal_length_size = (*extradata++ & 0x03) + 1;
+
+  GST_LOG ("Length Of Length is %d\n", h264_nal_length_size);
+  if (h264_nal_length_size == 3)
+  {
+    GST_ERROR ("LengthOfLength is WRONG...\n");
+    return FALSE;
+  }
+
+  /* retrieve sps and pps unit(s) */
+  unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */
+  GST_LOG ("No. of SPS units = %u\n", unit_nb);
+
+  if (!unit_nb)
+  {
+    GST_ERROR ("SPS is not present....\n");
+    return FALSE;
+  }
+
+  while (unit_nb--)
+  {
+    /* get SPS/PPS data Length*/
+    unit_size = PIFFDEMUX_RB16(extradata);
+
+    GST_LOG ("SPS size = %d", unit_size);
+
+    /* Extra 4 bytes for adding size of the packet */
+    total_size += unit_size + h264_nal_length_size;
+
+    /* Check if SPS/PPS Data Length crossed buffer Length */
+    if ((extradata + 2 + unit_size) > (dci_meta_buf + dci_meta_size))
+    {
+      GST_ERROR ("SPS Length is wrong in DCI...\n");
+      if (out)
+      {
+        free (out);
+      }
+      return FALSE;
+    }
+    out = realloc(out, total_size);
+    if (!out)
+    {
+      GST_ERROR ("realloc FAILED...\n");
+      return FALSE;
+    }
+    /* Copy length of SPS header */
+   // tmp = (unsigned int *)(out + total_size - unit_size - h264_nal_length_size);
+   // *tmp = unit_size;
+   (out + total_size - unit_size - h264_nal_length_size)[0] = 0;
+   (out + total_size - unit_size - h264_nal_length_size)[1] = 0;
+   (out + total_size - unit_size - h264_nal_length_size)[2] = 0;
+   (out + total_size - unit_size - h264_nal_length_size)[3] = (unsigned char)unit_size;
+
+   // memcpy(out + total_size - unit_size - h264_nal_length_size, &unit_size, h264_nal_length_size);
+   //g_print ("out[0] = %02x, out[1] = %02x, out[2] = %02x = out[3] = %02x\n",
+   //out[total_size - unit_size - h264_nal_length_size],  out[total_size - unit_size - h264_nal_length_size+1],
+   //out[total_size - unit_size - h264_nal_length_size + 2],  out[total_size - unit_size - h264_nal_length_size + 3]);
+
+    /* Copy SPS/PPS Length and data */
+    memcpy(out + total_size - unit_size,  extradata + PIFFDEMUX_SPSPPS_LENGTH_SIZE, unit_size);
+
+    extradata += (PIFFDEMUX_SPSPPS_LENGTH_SIZE + unit_size);
+
+    if (!unit_nb && !sps_done++)
+    {
+      /* Completed reading SPS data, now read PPS data */
+      unit_nb = *extradata++; /* number of pps unit(s) */
+      GST_DEBUG ("No. of PPS units = %d\n", unit_nb);
+    }
+  }
+
+  *dci_3gpp_buf = malloc (total_size);
+  if (NULL == *dci_3gpp_buf)
+  {
+    GST_ERROR ("Memory Allocation FAILED...\n");
+    free (out);
+    return FALSE;
+  }
+
+  memcpy(*dci_3gpp_buf, out, total_size);
+  *dci_3gpp_size = total_size;
+
+  GST_DEBUG ("SPS_PPS size = %d\n", total_size);
+
+  free(out);
+
+  return TRUE;
+ }
+
+#ifdef DRM_ENABLE
+static void
+piffdemux_get_playready_licence (GstPiffDemux *demux)
+{
+  int ret = -1;
+  drm_trusted_piff_get_license_info_s license_info;
+  drm_trusted_request_type_e request_type = DRM_TRUSTED_REQ_TYPE_PIFF_GET_LICENSE;
+
+  memset(&license_info, 0x00, sizeof(drm_trusted_piff_get_license_info_s));
+
+  license_info.lic_header.header = (unsigned char*) GST_BUFFER_DATA (demux->protection_header);
+  license_info.lic_header.header_len = GST_BUFFER_SIZE (demux->protection_header);
+
+  ret = drm_trusted_handle_request(request_type, (void *) &license_info, NULL);
+  if (DRM_TRUSTED_RETURN_SUCCESS != ret) {
+    GST_ERROR_OBJECT (demux,"failed to get license...");
+    GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to get license"), (NULL));
+    return;
+  }
+
+  GST_INFO_OBJECT (demux, "Got license....\n");
+
+  demux->encrypt_content = TRUE;
+
+  return;
+}
+
+void
+test_drm_trusted_operation_cb(drm_trusted_user_operation_info_s *operation_info, void *output_data)
+{
+       g_print ("Callback Hit:test_drm_trusted_operation_cb\n");
+       g_print ("operation_status=%d\n",operation_info->operation_status);
+       g_print ("operation_type=%d\n",operation_info->operation_type);
+}
+#endif
+
diff --git a/piffdemux/src/piffdemux.h b/piffdemux/src/piffdemux.h
new file mode 100755 (executable)
index 0000000..2147ea6
--- /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_PIFFDEMUX_H__
+#define __GST_PIFFDEMUX_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstadapter.h>
+#include "piffcommon.h"
+
+#ifdef DRM_ENABLE
+#include <drm_client.h>
+#include <drm_trusted_client.h>
+#include <drm_client_types.h>
+#include <drm_trusted_client_types.h>
+#endif
+
+G_BEGIN_DECLS
+
+GST_DEBUG_CATEGORY_EXTERN (piffdemux_debug);
+#define GST_CAT_DEFAULT piffdemux_debug
+
+#define GST_TYPE_PIFFDEMUX \
+  (gst_piffdemux_get_type())
+#define GST_PIFFDEMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PIFFDEMUX,GstPiffDemux))
+#define GST_PIFFDEMUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PIFFDEMUX,GstPiffDemuxClass))
+#define GST_IS_PIFFDEMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PIFFDEMUX))
+#define GST_IS_PIFFDEMUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PIFFDEMUX))
+
+#define GST_PIFFDEMUX_CAST(obj) ((GstPiffDemux *)(obj))
+
+/* piffdemux produces these for atoms it cannot parse */
+#define GST_PIFF_DEMUX_PRIVATE_TAG "private-piff-tag"
+#define GST_PIFF_DEMUX_CLASSIFICATION_TAG "classification"
+
+#define GST_PIFFDEMUX_MAX_STREAMS         8
+
+typedef struct _GstPiffDemux GstPiffDemux;
+typedef struct _GstPiffDemuxClass GstPiffDemuxClass;
+typedef struct _PiffDemuxStream PiffDemuxStream;
+
+struct _GstPiffDemux {
+  GstElement element;
+
+  /* pads */
+  GstPad *sinkpad;
+  GstPad *srcpad;
+
+  PiffDemuxStream *stream;
+
+  guint32 timescale;
+  gint64 duration;
+
+  gboolean fragmented;
+  guint64 moof_offset;
+  gint state;
+  gboolean posted_redirect;
+
+  /* push based variables */
+  guint neededbytes;
+  guint todrop;
+  GstAdapter *adapter;
+  GstBuffer *mdatbuffer;
+  guint64 mdatleft;
+
+  /* offset of the media data (i.e.: Size of header) */
+  guint64 offset;
+  /* offset of the mdat atom */
+  guint64 mdatoffset;
+  guint64 first_mdat;
+
+  GstTagList *tag_list;
+
+  /* configured playback region */
+  GstSegment segment;
+  gboolean segment_running;
+  GstEvent *pending_newsegment;
+
+  /* gst index support */
+  GstIndex *element_index;
+  gint index_id;
+
+  gint64 requested_seek_time;
+  guint64 seek_offset;
+  gboolean moof_rcvd;
+
+  /* live specific params */
+  piff_live_param_t *param;
+  guint lookahead_cnt;
+  gboolean is_live;
+
+  gboolean encrypt_content;
+  gboolean decrypt_init;
+#ifdef DRM_ENABLE
+  DRM_DECRYPT_HANDLE pr_handle;
+#endif
+  GstBuffer *protection_header;
+};
+
+struct _GstPiffDemuxClass {
+  GstElementClass parent_class;
+  void (*live_param)   (GstPiffDemux *piff, const piff_live_param_t *param);
+};
+
+GType gst_piffdemux_get_type (void);
+
+/* prepares video caps based on input params */
+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);
+/* prepares audio caps based on input params */
+void gst_piffdemux_set_audio_params (GstPiffDemux * piffdemux, guint fourcc, guint sampling_rate, guint bps,
+                                     guint channels, unsigned char *codec_data, unsigned int codec_data_len);
+G_END_DECLS
+
+#endif /* __GST_PIFFDEMUX_H__ */
+
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__ */
index 6bec15f..ca7c503 100755 (executable)
@@ -16,7 +16,9 @@ enum
   PROP_0,
   PROP_COOKIES,
   PROP_ALLOW_AUDIO_ONLY,
-  PROP_FRAGMENTS_CACHE,
+  PROP_CACHE_TIME,
+  PROP_LOW_PERCENTAGE,
+  PROP_HIGH_PERCENTAGE,
   PROP_BITRATE_SWITCH_TOLERANCE,
   PROP_LAST
 };
@@ -53,15 +55,16 @@ GST_DEBUG_CATEGORY_STATIC (gst_ss_demux_debug);
 static void
 _do_init (GType type)
 {
-  GST_DEBUG_CATEGORY_INIT (gst_ss_demux_debug, "ssdemux", 0,
-      "ssdemux element");
+  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_CACHE_TIME 6*GST_SECOND
 #define DEFAULT_BITRATE_SWITCH_TOLERANCE 0.4
+#define DEFAULT_LOW_PERCENTAGE 1
+#define DEFAULT_HIGH_PERCENTAGE 99
 
 struct _GstSSDemuxStream
 {
@@ -79,6 +82,9 @@ struct _GstSSDemuxStream
   GstBus *bus;
   GMutex *lock;
   GCond *cond;
+  GMutex *queue_lock;
+  GCond *queue_full;
+  GCond *queue_empty;
   guint frag_cnt;
   GQueue *queue;
   gchar *uri;
@@ -87,6 +93,17 @@ struct _GstSSDemuxStream
   GstCaps *caps;
   guint64 switch_ts;
   guint64 avg_dur;
+  gboolean is_buffering;
+  gint64 percent;
+  gboolean rcvd_percent;
+  guint64 push_block_time;
+  gint64 cached_duration;
+
+  /* for fragment download rate calculation */
+  guint64 download_start_ts;
+  guint64 download_stop_ts;
+  guint64 download_size;
+
 };
 
 static void gst_ss_demux_set_property (GObject * object, guint prop_id,
@@ -107,20 +124,18 @@ static gboolean gst_ss_demux_create_download_pipe (GstSSDemux * demux, GstSSDemu
 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_push_loop (GstSSDemuxStream *stream);
+static void gst_ss_demux_update_buffering (GstSSDemuxStream *stream, guint64 percent);
 
 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_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",
@@ -153,11 +168,22 @@ gst_ss_demux_class_init (GstSSDemuxClass * klass)
           "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_object_class_install_property (gobject_class, PROP_CACHE_TIME,
+      g_param_spec_uint64 ("max-cache-time", "caching time",
+          "amount of data that can be cached in seconds", 0, G_MAXUINT64,
+          DEFAULT_CACHE_TIME,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_LOW_PERCENTAGE,
+      g_param_spec_int ("low-percent", "Low Percent",
+          "Low threshold to start buffering",
+          1, 100, DEFAULT_LOW_PERCENTAGE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_HIGH_PERCENTAGE,
+      g_param_spec_int ("high-percent", "High percent",
+          "High threshold to complete buffering",
+          2, 100, DEFAULT_HIGH_PERCENTAGE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_BITRATE_SWITCH_TOLERANCE,
@@ -183,12 +209,15 @@ gst_ss_demux_init (GstSSDemux * demux, GstSSDemuxClass * klass)
       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->max_cache_time = DEFAULT_CACHE_TIME;
   demux->cookies = NULL;
   demux->ss_mode = SS_MODE_NO_SWITCH;
   demux->switch_eos = FALSE;
+  demux->allow_audio_only = FALSE;
+  demux->percent = 100;
+  demux->low_percent = DEFAULT_LOW_PERCENTAGE;
+  demux->high_percent = DEFAULT_HIGH_PERCENTAGE;
+  demux->eos = FALSE;
 }
 
 static void
@@ -199,6 +228,8 @@ gst_ss_demux_dispose (GObject * obj)
 
   for (n = 0; n < SS_STREAM_NUM; n++) {
     if (demux->streams[n]) {
+      gst_pad_stop_task ((demux->streams[n])->pad);
+      g_print ("\n\n\nstopped the TASK\n\n\n");
       gst_ss_demux_stream_free (demux, demux->streams[n]);
       demux->streams[n] = NULL;
     }
@@ -226,8 +257,14 @@ gst_ss_demux_set_property (GObject * object, guint prop_id,
     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);
+    case PROP_CACHE_TIME:
+      demux->max_cache_time = g_value_get_uint64 (value);
+      break;
+    case PROP_LOW_PERCENTAGE:
+      demux->low_percent = g_value_get_int (value);
+      break;
+    case PROP_HIGH_PERCENTAGE:
+      demux->high_percent = g_value_get_int (value);
       break;
     case PROP_BITRATE_SWITCH_TOLERANCE:
       demux->bitrate_switch_tol = g_value_get_float (value);
@@ -251,8 +288,14 @@ gst_ss_demux_get_property (GObject * object, guint prop_id, GValue * value,
     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);
+    case PROP_CACHE_TIME:
+      g_value_set_uint64 (value, demux->max_cache_time);
+      break;
+    case PROP_LOW_PERCENTAGE:
+      g_value_set_int (value, demux->low_percent);
+      break;
+    case PROP_HIGH_PERCENTAGE:
+      g_value_set_int (value, demux->high_percent);
       break;
     case PROP_BITRATE_SWITCH_TOLERANCE:
       g_value_set_float (value, demux->bitrate_switch_tol);
@@ -267,7 +310,7 @@ static gboolean
 gst_ss_demux_sink_event (GstPad * pad, GstEvent * event)
 {
   GstSSDemux *demux = GST_SS_DEMUX (gst_pad_get_parent (pad));
-  GstQuery *query;
+  GstQuery *query = NULL;
   gboolean ret;
   gchar *uri;
 
@@ -275,8 +318,8 @@ gst_ss_demux_sink_event (GstPad * pad, GstEvent * event)
     case GST_EVENT_EOS: {
       int i = 0;
       if (demux->manifest == NULL) {
-        GST_WARNING_OBJECT (demux, "Received EOS without a manifest.");
-        break;
+        GST_ERROR_OBJECT (demux, "Received EOS without a manifest.");
+        goto error;
       }
 
       GST_DEBUG_OBJECT (demux, "Got EOS on the sink pad: mainifest file fetched");
@@ -289,18 +332,38 @@ gst_ss_demux_sink_event (GstPad * pad, GstEvent * event)
         g_free (uri);
       } else {
         GST_ERROR_OBJECT (demux, "failed to query URI from upstream");
-        return FALSE;
+        goto error;
       }
       gst_query_unref (query);
+      query = NULL;
 
       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;
+        GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid playlist."), (NULL));
+        goto error;
+      }
+
+      {
+        unsigned char *protection_data = NULL;
+        unsigned int protection_len = 0;
+
+        /* get protection-header from manifest parser */
+        ret = gst_ssm_parse_get_protection_header (demux->parser, &protection_data, &protection_len);
+        if (!ret) {
+          GST_ERROR_OBJECT (demux, "failed to get protection header...");
+          GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("fragment allocation failed..."), (NULL));
+          goto error;
+        }
+
+        if (protection_data && protection_len) {
+          g_print ("Got the protection header...\n");
+          demux->protection_header = gst_buffer_new ();
+          GST_BUFFER_DATA (demux->protection_header) = GST_BUFFER_MALLOCDATA (demux->protection_header) = protection_data;
+          GST_BUFFER_SIZE (demux->protection_header) = protection_len;
+        }
       }
 
       for( i = 0; i < SS_STREAM_NUM; i++) {
@@ -309,9 +372,30 @@ gst_ss_demux_sink_event (GstPad * pad, GstEvent * event)
 
           // Add pad emission of the stream
           gst_ss_demux_stream_init (demux, stream, i);
+
+          if (!gst_pad_is_linked (stream->pad)) {
+            GST_WARNING_OBJECT (demux, "%s - stream pad is not linked...clean up", ssm_parse_get_stream_name(i));
+            gst_ss_demux_stream_free (demux, stream);
+            continue;
+          }
+
+          /* create stream task */
           g_static_rec_mutex_init (&stream->stream_lock);
           stream->stream_task = gst_task_create ((GstTaskFunction) gst_ss_demux_stream_loop, demux);
+          if (NULL == stream->stream_task) {
+            GST_ERROR_OBJECT (demux, "failed to create stream task...");
+            GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to create stream task"), (NULL));
+            goto error;
+          }
           gst_task_set_lock (stream->stream_task, &stream->stream_lock);
+
+          /* create stream push loop */
+          if (!gst_pad_start_task (stream->pad, (GstTaskFunction) gst_ss_demux_push_loop, stream)) {
+            GST_ERROR_OBJECT (demux, "failed to create push loop...");
+            GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to create push loop"), (NULL));
+            goto error;
+          }
+
           demux->streams[i] = stream;
           g_print ("Starting stream - %d task loop...\n", i);
           gst_task_start (stream->stream_task);
@@ -319,17 +403,33 @@ gst_ss_demux_sink_event (GstPad * pad, GstEvent * event)
       }
 
       gst_event_unref (event);
+      gst_object_unref (demux);
       return TRUE;
     }
     case GST_EVENT_NEWSEGMENT:
       /* Swallow newsegments, we'll push our own */
       gst_event_unref (event);
+      gst_object_unref (demux);
       return TRUE;
     default:
       break;
   }
 
   return gst_pad_event_default (pad, event);
+
+error:
+  // TODO: add closing
+
+  //gst_ss_demux_stop (demux);
+  gst_event_unref (event);
+  gst_object_unref (demux);
+
+  if (query)
+    gst_query_unref (query);
+
+  g_print ("Returning from sink event...\n");
+  return FALSE;
+
 }
 
 static gboolean
@@ -517,19 +617,105 @@ gst_ss_demux_get_next_fragment (GstSSDemux * demux, SS_STREAM_TYPE stream_type)
 
 error:
   {
+    GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to download fragment"), (NULL));
     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 ());
+    demux->eos = TRUE;
     gst_ss_demux_stop (demux, stream);
     return TRUE;
   }
 }
 
 static void
+gst_ss_demux_push_loop (GstSSDemuxStream *stream)
+{
+  GstBuffer *outbuf = NULL;
+  GstSSDemux *demux = stream->parent;
+  GstFlowReturn fret = GST_FLOW_OK;
+
+  // TODO: need to take care of EOS handling....
+
+  g_mutex_lock (stream->queue_lock);
+
+  if (g_queue_is_empty (stream->queue)) {
+    GST_DEBUG_OBJECT (stream->pad,"queue is empty wait till, some buffers are available...");
+    if (demux->eos) {
+      GST_INFO_OBJECT (stream->pad, "stream EOS, pause the task");
+      gst_pad_push_event (stream->pad, gst_event_new_eos ());
+      gst_pad_pause_task (stream->pad);
+      g_print ("Paused the task");
+      return;
+    }
+    g_cond_wait (stream->queue_empty, stream->queue_lock);
+  }
+
+  outbuf = g_queue_pop_head (stream->queue);
+
+  if (GST_BUFFER_DURATION_IS_VALID (outbuf)) {
+    stream->cached_duration -= GST_BUFFER_DURATION(outbuf);
+  } else {
+    g_print ("\nDuration field is not valid.. check this issue !!!!!!!!\n");
+    GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid duration of a frame"), (NULL));
+    g_mutex_unlock (stream->queue_lock);
+    return;
+  }
+
+  g_cond_signal (stream->queue_full);
+  //g_print ("[%s] Signalled full condition...\n", ssm_parse_get_stream_name(stream->type));
+  g_mutex_unlock (stream->queue_lock);
+
+  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; // No need to close task for this, because sometimes pad can unlined
+    }
+    stream->sent_ns = TRUE;
+  }
+
+  if (stream->type == SS_STREAM_VIDEO && demux->ss_mode == SS_MODE_AONLY) {
+    GST_BUFFER_TIMESTAMP (outbuf) = stream->switch_ts;
+    GST_BUFFER_DURATION (outbuf) = ((float)1/25) * GST_SECOND;
+    stream->switch_ts = GST_BUFFER_TIMESTAMP (outbuf) + GST_BUFFER_DURATION (outbuf);
+    g_print ("Dummy buffers ts : %"GST_TIME_FORMAT" and dur : %"GST_TIME_FORMAT"\n",
+             GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (outbuf)), GST_TIME_ARGS(GST_BUFFER_DURATION (outbuf)));
+    gchar *caps_string = gst_caps_to_string(GST_BUFFER_CAPS(outbuf));
+    g_print ("caps : %s\n", caps_string);
+    g_free(caps_string);
+    caps_string = NULL;
+  }
+
+  /* push data to downstream*/
+  fret = gst_pad_push (stream->pad, outbuf);
+  if (fret != GST_FLOW_OK) {
+    GST_ERROR_OBJECT (demux, "failed to push data, reason : %s", gst_flow_get_name (fret));
+    goto error;
+  }
+
+  //g_print ("[%s] pushed buffer\n", ssm_parse_get_stream_name(stream->type));
+error:
+  // TODO: need to close task & post error to bus
+  return;
+}
+
+static void
 gst_ss_demux_stream_loop (GstSSDemux * demux)
 {
   GThread *self = NULL;
@@ -539,16 +725,18 @@ gst_ss_demux_stream_loop (GstSSDemux * demux)
   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) {
+    if (demux->streams[stream_type] && 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;
+  if (stream) {
+    /* 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;
@@ -567,6 +755,7 @@ static gboolean
 gst_ss_demux_download_fragment (GstSSDemux *demux, GstSSDemuxStream *stream, const gchar * uri, guint64 start_ts)
 {
   GstStateChangeReturn ret;
+  GTimeVal time = {0, };
 
   g_print ("Going to download fragment : %s\n", uri);
   if (!gst_ss_demux_create_download_pipe (demux, stream, uri, start_ts)) {
@@ -574,6 +763,10 @@ gst_ss_demux_download_fragment (GstSSDemux *demux, GstSSDemuxStream *stream, con
     return FALSE;
   }
 
+  /* download rate calculation : note down start time*/
+  g_get_current_time (&time);
+  stream->download_start_ts = (time.tv_sec * 1000000)+ time.tv_usec;
+
   ret = gst_element_set_state (stream->pipe, GST_STATE_PLAYING);
   if (ret == GST_STATE_CHANGE_FAILURE) {
     GST_ERROR_OBJECT (demux, "set_state failed...");
@@ -711,7 +904,7 @@ static gboolean
 gst_ss_demux_create_download_pipe (GstSSDemux * demux, GstSSDemuxStream *stream, const gchar * uri, guint64 start_ts)
 {
   gchar *name = NULL;
-  GstCaps *caps = NULL;
+  gchar *caps_string = NULL;
 
   if (!gst_uri_is_valid (uri))
     return FALSE;
@@ -721,18 +914,19 @@ gst_ss_demux_create_download_pipe (GstSSDemux * demux, GstSSDemuxStream *stream,
   stream->pipe = gst_pipeline_new (name);
   if (!stream->pipe) {
     GST_ERROR_OBJECT (demux, "failed to create pipeline");
+    g_free(name);
+    name = NULL;
     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");
+    g_free(name);
     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);
@@ -743,32 +937,40 @@ gst_ss_demux_create_download_pipe (GstSSDemux * demux, GstSSDemuxStream *stream,
   stream->parser = gst_element_factory_make ("piffdemux", name);
   if (!stream->parser) {
     GST_ERROR_OBJECT (demux, "failed to create piffdemux element");
+    g_free(name);
+    name = NULL;
     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));
+  if (stream->caps)
+    gst_caps_unref (stream->caps);
 
-  g_object_set (G_OBJECT (stream->parser), "caps", caps, NULL);
+  stream->caps = ssm_parse_get_stream_caps (demux->parser, stream->type);
+  caps_string = gst_caps_to_string(stream->caps);
+  GST_INFO_OBJECT (stream->pad, "prepare caps = %s", caps_string);
+  g_free(caps_string);
+  caps_string = NULL;
+
+  g_object_set (G_OBJECT (stream->parser), "caps", stream->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);
+  if (demux->protection_header)
+    g_object_set (G_OBJECT (stream->parser), "protection-header", demux->protection_header, 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");
+    g_free(name);
+    name = NULL;
     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...");
@@ -779,6 +981,9 @@ gst_ss_demux_create_download_pipe (GstSSDemux * demux, GstSSDemuxStream *stream,
   gst_bus_add_watch (stream->bus, (GstBusFunc)gst_ss_demux_download_bus_cb, stream);
   gst_object_unref (stream->bus);
 
+  g_free(name);
+  name = NULL;
+
   return TRUE;
 }
 
@@ -937,20 +1142,27 @@ gst_ss_demux_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
 
   switch (GST_MESSAGE_TYPE(msg)) {
     case GST_MESSAGE_EOS: {
-      guint64 download_rate = -1;
+      GTimeVal time = {0, };
+      gint idx = 0;
+      guint64 total_push_time = 0;
+      guint64 download_rate = 0;
 
       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);
-      }
+      /* download rate calculation : note down start time*/
+      g_get_current_time (&time);
+      stream->download_stop_ts = (time.tv_sec * 1000000)+ time.tv_usec;
 
-      // 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) {
+      download_rate = ((stream->download_size * 8 * 1000000) / (stream->download_stop_ts - stream->download_start_ts - stream->push_block_time));
+      g_print("*********** '%s' download rate = %"G_GUINT64_FORMAT" bpssss **************\n", stream->name, download_rate);
+      stream->download_size = 0;
+      stream->download_stop_ts = stream->download_start_ts = 0;
+      stream->push_block_time = 0;
+
+      if ((stream->type == SS_STREAM_VIDEO) && (demux->ss_mode != SS_MODE_AONLY)) {
+        if (!stream->is_buffering) {
           /* for switching, we are considering video download rate only */
           demux->ss_mode = gst_ssm_parse_switch_qualitylevel (demux->parser, download_rate);
         }
@@ -983,19 +1195,21 @@ gst_ss_demux_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
 
       g_print ("Error from %s\n", gst_element_get_name (GST_MESSAGE_SRC(msg)));
 
-      gst_message_parse_error( msg, &error, &debug );
+      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)) {
+      if (GST_IS_URI_HANDLER(GST_MESSAGE_SRC(msg))) {
         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);
+        if (error)
+          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 */
@@ -1008,6 +1222,9 @@ gst_ss_demux_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
           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");
+            g_free(debug);
+            debug = NULL;
+
             return FALSE;
           }
         }
@@ -1028,9 +1245,9 @@ gst_ss_demux_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
           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);
+            g_free(debug);
             debug = NULL;
-            g_error_free( error);
+            g_error_free(error);
             return FALSE;
         }
         gst_ss_demux_stop (demux, stream);
@@ -1041,6 +1258,44 @@ gst_ss_demux_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
       g_error_free( error);
       break;
     }
+    case GST_MESSAGE_BUFFERING: {
+      int n =0;
+      int total_cache_perc = 0;
+      int active_stream_cnt = 0;
+      GstSSDemuxStream *cur_stream = NULL;
+      int avg_percent = 0;
+
+      /* update buffer percent */
+      gst_message_parse_buffering (msg, &stream->rcvd_percent);
+      gchar *name = gst_element_get_name (GST_MESSAGE_SRC (msg));
+      GST_LOG_OBJECT (stream->pad, "Internal bus : Buffering from %s = %d\n", name, stream->rcvd_percent);
+      g_free(name);
+      name = NULL;
+      // TODO: need to check for better logic
+      for (n = 0; n < SS_STREAM_NUM; n++) {
+        cur_stream = demux->streams[n];
+        if (cur_stream) {
+          active_stream_cnt++;
+          total_cache_perc += cur_stream->rcvd_percent;
+        }
+      }
+
+      avg_percent = total_cache_perc / active_stream_cnt;
+
+      GST_LOG_OBJECT (demux, "avg buffering completed = %d", avg_percent);
+
+      if (avg_percent > 100)
+        avg_percent = 100;
+
+      // TODO: need to add mutex for protecting percent
+      if (avg_percent != demux->percent) {
+        demux->percent = avg_percent;
+        GST_LOG_OBJECT (demux, "#########Posting %d buffering msg to main bus ###########", demux->percent);
+
+        gst_element_post_message (GST_ELEMENT (demux), gst_message_new_buffering (GST_OBJECT (demux), avg_percent));
+      }
+    }
+    break;
     case GST_MESSAGE_WARNING: {
       char* debug = NULL;
       GError* error = NULL;
@@ -1061,12 +1316,60 @@ gst_ss_demux_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
 }
 
 static void
+gst_ss_demux_update_buffering (GstSSDemuxStream *stream, guint64 percent)
+{
+  gboolean do_post = FALSE;
+  GstSSDemux *demux = stream->parent;
+
+  if (stream->is_buffering) {
+    do_post = TRUE;
+    if (percent >= demux->high_percent)
+      stream->is_buffering = FALSE;
+  } else {
+    if (percent < demux->low_percent) {
+      stream->is_buffering = TRUE;
+      do_post = TRUE;
+    }
+  }
+
+  if (do_post) {
+    GstMessage *message;
+    GstBufferingMode mode;
+    gint64 buffering_left = -1;
+
+    percent = percent * 100 / demux->high_percent;
+
+    if (percent > 100)
+      percent = 100;
+
+    if (percent != stream->percent) {
+      stream->percent = percent;
+
+      GST_DEBUG_OBJECT (stream->pad, "buffering %d percent", (gint) percent);
+      g_print ("'%s' buffering %d percent done\n", stream->name, (gint) percent);
+
+      /* posting buffering to internal bus, which will take average & post to main bus */
+      message = gst_message_new_buffering (GST_OBJECT_CAST (stream->sink), (gint) percent);
+      gst_element_post_message (GST_ELEMENT_CAST (stream->sink), message);
+    }
+  }
+
+}
+
+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;
+  GstBuffer *headbuf = NULL;
+  gint64 diff = 0;
+  gint64 percent = 0;
+  GTimeVal start = {0, };
+  GTimeVal stop = {0, };
+  guint64 push_start_time = 0;
+  guint64 push_end_time =0;
 
   inbuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
   if (!inbuf) {
@@ -1074,67 +1377,57 @@ gst_ssm_demux_on_new_buffer (GstElement * appsink, void* data)
     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;
+  g_mutex_lock (stream->queue_lock);
 
-    duration = gst_util_uint64_scale (GST_SSM_PARSE_GET_DURATION(demux->parser), GST_SECOND,
-               GST_SSM_PARSE_GET_TIMESCALE(demux->parser));
+  stream->download_size += GST_BUFFER_SIZE(inbuf);
 
-    start = gst_util_uint64_scale (GST_SSM_PARSE_NS_START(demux->parser), GST_SECOND,
-               GST_SSM_PARSE_GET_TIMESCALE(demux->parser));
+  /* download rate calculation : note push_start_ts */
+  g_get_current_time (&start);
+  push_start_time = (start.tv_sec * 1000000)+ start.tv_usec;
 
-    event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
-                                       start, duration, start);
+  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)));
 
-    GST_DEBUG_OBJECT(demux," new_segment start = %"GST_TIME_FORMAT, GST_TIME_ARGS(start));
+  g_queue_push_tail (stream->queue, inbuf);
 
-    if (!gst_pad_push_event (stream->pad, event)) {
-      GST_ERROR_OBJECT (demux, "failed to push newsegment event");
-      return;
-    }
-    stream->sent_ns = TRUE;
+  if (GST_BUFFER_DURATION_IS_VALID (inbuf)) {
+    stream->cached_duration += GST_BUFFER_DURATION(inbuf);
+  } else {
+    g_print ("\nDuration field is not valid.. check this issue !!!!!!!!\n");
+    GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid duration of a frame"), (NULL));
+    g_mutex_unlock (stream->queue_lock);
+    return;
   }
 
-  while (!g_queue_is_empty(stream->queue)) {
-    GstBuffer *cache_buf = g_queue_pop_head (stream->queue);
+  if (stream->cached_duration >= 0) {
+    percent = (stream->cached_duration * 100) / demux->max_cache_time;
+    //g_print ("[%s] percent done = %d[%"G_GINT64_FORMAT"]\n", ssm_parse_get_stream_name(stream->type), percent, percent);
 
-    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;
+    // TODO: need to decide, whther to call before wait or after ??
+    gst_ss_demux_update_buffering (stream, percent);
+
+    if (percent > 100) {
+      /* update buffering & wait if space is not available */
+      GST_DEBUG_OBJECT (stream->pad, "Reached more than 100 percent, queue full & wait till free");
+      g_cond_wait(stream->queue_full, stream->queue_lock);
+      GST_DEBUG_OBJECT (stream->pad,"Received signal to add more data...");
     }
+  } else {
+    g_print ("cached duration can not be negative\n\n\n");
+    GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid cached duration"), (NULL));
+    g_mutex_unlock (stream->queue_lock);
+    return;
   }
 
-  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)));
+  /* download rate calculation : note push_stop_ts */
+  g_get_current_time (&stop);
+  push_end_time = (stop.tv_sec * 1000000)+ stop.tv_usec;
 
-    g_print ("caps : %s\n", gst_caps_to_string(GST_BUFFER_CAPS(inbuf)));
-  }
+  stream->push_block_time += push_end_time - push_start_time;
 
-  /* 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;
-  }
+  g_cond_signal (stream->queue_empty);
 
-error:
+  g_mutex_unlock (stream->queue_lock);
   return;
 }
 
@@ -1151,6 +1444,9 @@ gst_ss_demux_stream_init (GstSSDemux *demux, GstSSDemuxStream *stream, SS_STREAM
   stream->cond = g_cond_new ();
   stream->lock = g_mutex_new ();
   stream->queue = g_queue_new ();
+  stream->queue_full = g_cond_new ();
+  stream->queue_empty = g_cond_new ();
+  stream->queue_lock = g_mutex_new ();
   stream->parent = demux;
   stream->pipe = NULL;
   stream->urisrc = NULL;
@@ -1163,6 +1459,13 @@ gst_ss_demux_stream_init (GstSSDemux *demux, GstSSDemuxStream *stream, SS_STREAM
   stream->sent_ns = FALSE;
   stream->switch_ts = GST_CLOCK_TIME_NONE;
   stream->avg_dur = GST_CLOCK_TIME_NONE;
+  stream->percent = 100;
+  stream->rcvd_percent = 0;
+  stream->push_block_time = 0;
+  stream->cached_duration = 0;
+  stream->download_start_ts = 0;
+  stream->download_stop_ts = 0;
+  stream->download_size = 0;
 
   if (stream->type == SS_STREAM_VIDEO) {
     stream->pad = gst_pad_new_from_static_template (&ssdemux_videosrc_template, "video");
@@ -1182,7 +1485,9 @@ gst_ss_demux_stream_init (GstSSDemux *demux, GstSSDemuxStream *stream, SS_STREAM
   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));
+  gchar *caps_name = gst_caps_to_string(stream->caps);
+  g_print ("prepare video caps = %s", caps_name);
+  g_free(caps_name);
 
   GST_DEBUG_OBJECT (demux, "setting caps %" GST_PTR_FORMAT, stream->caps);
   gst_pad_set_caps (stream->pad, stream->caps);
@@ -1215,7 +1520,18 @@ gst_ss_demux_stream_free (GstSSDemux * demux, GstSSDemuxStream * stream)
     g_mutex_free (stream->lock);
     stream->lock = NULL;
   }
-
+  if (stream->queue_lock) {
+    g_mutex_free (stream->queue_lock);
+    stream->queue_lock = NULL;
+  }
+  if (stream->queue_full) {
+    g_cond_free (stream->queue_full);
+    stream->queue_full = NULL;
+  }
+  if (stream->queue_empty) {
+    g_cond_free (stream->queue_empty);
+    stream->queue_empty= NULL;
+  }
   g_free (stream);
 }
 static gboolean
index adc5525..b230b96 100755 (executable)
@@ -40,17 +40,18 @@ struct _GstSSDemux
   /* 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
+  guint64 max_cache_time;\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
+  gint percent;\r
+  gint low_percent;\r
+  gint high_percent;\r
+  gboolean eos;\r
   GstSSDemuxStream *streams[SS_STREAM_NUM];\r
   SS_BW_MODE ss_mode;\r
   gboolean switch_eos;\r
+  GstBuffer *protection_header;\r
 };\r
 \r
 struct _GstSSDemuxClass\r
index fd0f41c..45268ab 100755 (executable)
@@ -30,7 +30,7 @@ int_from_string (gchar * ptr, gchar ** endptr, gint * val, gint base)
   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));
+    g_print ("Error in strtol : %s\n", g_strerror(errno));
     return FALSE;
   }
 
@@ -105,7 +105,7 @@ ssm_parse_get_xml_prop_uint64 (GstSSMParse *parser,
   }
 
   return prop_uint64;
-} 
+}
 
 static gint
 ssm_parser_sort_qualitylevels_by_bitrate (gconstpointer a, gconstpointer b)
@@ -235,6 +235,22 @@ gst_ssm_parse_free (GstSSMParse *parser)
 
 
 static gboolean
+gst_ssm_parse_confirm_audiotag(gchar ** fourcc, gint audio_tag)
+{
+  switch(audio_tag){
+    case 255:
+      *fourcc = (gchar *)strdup("AACL");
+      break;
+    case 353:
+      *fourcc = (gchar *)strdup("WMAP");
+      break;
+    default:
+      return FALSE;
+  }
+  return TRUE;
+}
+
+static gboolean
 ssm_parse_quality_node (GstSSMParse *parser, GstSSMStreamNode *stream, xmlNodePtr quality_node)
 {
   GstSSMQualityNode *quality_level = NULL;
@@ -326,19 +342,24 @@ ssm_parse_quality_node (GstSSMParse *parser, GstSSMStreamNode *stream, xmlNodePt
 
   /* 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){
+    if(!gst_ssm_parse_confirm_audiotag(&quality_level->fourcc, quality_level->audio_tag)){
+      GST_ERROR ("failed to set fourcc from audio tag %d",quality_level->audio_tag);
+      return FALSE;
+    }
+  }
+
   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) ||
+  if (quality_level->fourcc && !((!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;
-    }
+    free (quality_level->fourcc);
+
     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) ||
@@ -1059,9 +1080,11 @@ ssm_prepare_video_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
                      NULL);
   }
 
-  GST_INFO ( "prepared video caps : %s\n", gst_caps_to_string(caps));
+  gchar *caps_name = gst_caps_to_string(caps);
+  GST_INFO ( "prepared video caps : %s\n", caps_name);
+  g_free(caps_name);
 
-   return caps;
+  return caps;
 }
 
 GstCaps *
@@ -1071,8 +1094,10 @@ ssm_prepare_audio_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
   GstBuffer *codec_data = NULL;
   GstCaps *caps = NULL;
 
-  if ((!strncmp ((char *)cur_quality_node->fourcc, "AACL", 4)) || !strncmp ((char *)cur_quality_node->fourcc, "WMAP", 4)) {
+  if (cur_quality_node->codec_data &&
+     ((!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 *dci = cur_quality_node->codec_data;
     gchar tmp[3] = {0, };
     gint val = 0;
     gint codec_data_len = (DCI_len >>1);
@@ -1087,14 +1112,14 @@ ssm_prepare_audio_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
     /* copy codec data */
     while (DCI_len) {
       memset (tmp, 0x00, 3);
-      strncpy ((char*)tmp, (char*)cur_quality_node->codec_data, 2);
+      strncpy ((char*)tmp, (char*)dci, 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 += 2;
       DCI_len = DCI_len - 2;
       //g_print ("val = 0x%02x, codec_data_length = %d, idx = %d\n", val, DCI_len, idx);
       idx++;
@@ -1111,6 +1136,7 @@ ssm_prepare_audio_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
                           "stream-format", G_TYPE_STRING, "raw",
                           "rate", G_TYPE_INT, (int) cur_quality_node->samplingrate,
                           "channels", G_TYPE_INT, cur_quality_node->channels,
+                          "codec_data", GST_TYPE_BUFFER, codec_data,
                           NULL);
   } else if (!strncmp ((char *)cur_quality_node->fourcc, "WMAP", 4)) {
     caps = gst_caps_new_simple ("audio/x-wma",
@@ -1127,7 +1153,9 @@ ssm_prepare_audio_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
                              "channels", G_TYPE_INT, cur_quality_node->channels,
                              NULL);
   }
-  GST_INFO ( "prepared video caps : %s\n", gst_caps_to_string(caps));
+  gchar *caps_name = gst_caps_to_string(caps);
+  GST_INFO ( "prepared video caps : %s\n", caps_name);
+  g_free(caps_name);
 
   return caps;
 }
@@ -1152,6 +1180,7 @@ gst_ssm_parse_switch_qualitylevel (GstSSMParse *parser, guint drate)
       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;
+      bitrate = ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate;
     } else {
       g_print ("Already at MAX Bitrate possible...\n");
       ret = SS_MODE_NO_SWITCH;
@@ -1164,6 +1193,7 @@ gst_ssm_parse_switch_qualitylevel (GstSSMParse *parser, guint drate)
     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);
+      bitrate = ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate;
     } else {
       g_print ("Reached MIN video bitrate possible...\n");
       if (GST_SSM_PARSE_IS_LIVE_PRESENTATION(parser)) {
@@ -1271,25 +1301,30 @@ gst_ssm_parse_seek_manifest (GstSSMParse *parser, guint64 seek_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,
+          if(stream->fragment_lists && stream->fragment_lists->data) {
+            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_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;
+        if(stream->fragment_lists && stream->fragment_lists->data)
+          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,
+          if(stream->fragment_lists && stream->fragment_lists->data) {
+            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));
+            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;
+          }
         }
-        start_ts = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
       } else {
         /* rare case */
         start_ts = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
@@ -1313,6 +1348,29 @@ gst_ssm_parse_seek_manifest (GstSSMParse *parser, guint64 seek_time)
   return TRUE;
 }
 
+gboolean
+gst_ssm_parse_get_protection_header (GstSSMParse *parser, unsigned char **protection_header, unsigned int *protection_header_len)
+{
+  if (!parser->RootNode->ProtectNode) {
+    *protection_header = NULL;
+    *protection_header_len = 0;
+    return TRUE;
+  }
+
+  if (parser->RootNode->ProtectNode->ContentSize && parser->RootNode->ProtectNode->Content) {
+    *protection_header = g_malloc0 (parser->RootNode->ProtectNode->ContentSize);
+    if (*protection_header == NULL) {
+      GST_ERROR ("failed to allocate memory...");
+      return FALSE;
+    }
+
+    memcpy (*protection_header, parser->RootNode->ProtectNode->Content, parser->RootNode->ProtectNode->ContentSize);
+    *protection_header_len = parser->RootNode->ProtectNode->ContentSize;
+  }
+
+  return TRUE;
+}
+
 static gboolean
 convert_NALUnitDCI_to_PacktizedDCI (unsigned char *nalu_dci, unsigned char **packetized_dci, unsigned int *packetized_dci_len)
 {
@@ -1605,3 +1663,6 @@ exit:
 #endif
 }
 
+
+
+
index 21c4042..16c900c 100755 (executable)
@@ -121,9 +121,9 @@ gboolean gst_ssm_parse_manifest (GstSSMParse *parser, char *data, unsigned int s
 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);
+SS_BW_MODE gst_ssm_parse_switch_qualitylevel (GstSSMParse *parser, guint drate);
 gboolean gst_ssm_parse_seek_manifest (GstSSMParse *parser, guint64 seek_time);
+gboolean gst_ssm_parse_get_protection_header (GstSSMParse *parser, unsigned char **protection_header, unsigned int *protection_header_len);
 G_END_DECLS
 #endif /* __SS_MANIFEST_PARSE_H__ */
 
diff --git a/submux/Makefile.am b/submux/Makefile.am
new file mode 100755 (executable)
index 0000000..308a09c
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = src\r
diff --git a/submux/src/Makefile.am b/submux/src/Makefile.am
new file mode 100755 (executable)
index 0000000..695e81c
--- /dev/null
@@ -0,0 +1,27 @@
+# plugindir is set in configure
+
+##############################################################################
+# change libgstplugin.la to something more suitable, e.g. libmysomething.la  #
+##############################################################################
+plugin_LTLIBRARIES = libgstsubmux.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
+libgstsubmux_la_SOURCES = gstsubmux.c
+
+# flags used to compile this plugin
+# add other _CFLAGS and _LIBS as needed
+libgstsubmux_la_CFLAGS = $(GST_CFLAGS) $(DRM_CLIENT_CFLAGS) $(DRM_TRUSTED_CFLAGS) $(MMTA_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+libgstsubmux_la_LIBADD = $(GST_LIBS) $(DRM_CLIENT_LIBS)$(DRM_TRUSTED_LIBS) $(GST_BASE_LIBS) $(MMTA_LIBS)$(GST_APP_LIBS) -lgstapp-0.10 $(CRYPTO_LIBS)
+libgstsubmux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+
+# headers we need but don't want installed
+noinst_HEADERS = gstsubmux.h
+
diff --git a/submux/src/gstsubmux.c b/submux/src/gstsubmux.c
new file mode 100755 (executable)
index 0000000..98566e2
--- /dev/null
@@ -0,0 +1,2451 @@
+/*
+ * SLP2.0
+ * Copyright (c) 2011 Samsung Electronics, Inc.
+ * All rights reserved.
+ *
+ * This software is a confidential and proprietary information
+ * of Samsung Electronics, Inc. ("Confidential Information").  You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Samsung Electronics.
+ */
+
+/*
+ * @file        gstsubmux.c
+ * @author      Deepak Singh (deep.singh@samsung.com)
+ * @version     1.0
+ * @brief       This source code implements the gstreamer plugin for subtitle muxing requirement in media player.
+ *
+ */
+
+/*! Revision History:
+ *! ---------------------------------------------------------------------------
+ *!     DATE     |         AUTHOR               |             COMMENTS
+ *! ---------------------------------------------------------------------------
+ *! 1-4-2014        deep.singh@samsung.com                   created.
+ */
+
+#include "config.h"
+#include "gstsubmux.h"
+#include <gst/base/gstadapter.h>
+#include <glib/gstdio.h>
+#include <gst/gst.h>
+#include <gst/app/gstappsink.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <gst/tag/tag.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <gst/gst.h>
+static const GstElementDetails gst_submux_plugin_details = GST_ELEMENT_DETAILS(
+    "submux",
+    "Codec/Parser/Subtitle",
+    "muxing of different subtitle stream",
+    "Samsung Electronics <www.samsung.com>"
+);
+static GstStaticPadTemplate gst_submux_sink_template = GST_STATIC_PAD_TEMPLATE(
+    "sink%d",
+    GST_PAD_SINK,
+    GST_PAD_REQUEST,
+    GST_STATIC_CAPS("video/x-dvd-subpicture; text/plain; application/x-subtitle; "
+                    "text/x-pango-markup;"
+                    "application/x-usf; subpicture/x-pgs; subtitle/x-kate; application/x-subtitle; "
+                    "application/x-subtitle-sami; application/x-subtitle-tmplayer; "
+                    "application/x-subtitle-mpl2; application/x-subtitle-dks; "
+                    "application/x-subtitle-qttext")
+);
+static GstStaticPadTemplate gst_submux_src_template = GST_STATIC_PAD_TEMPLATE(
+    "src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("text/plain; text/x-pango-markup")
+);
+enum
+{
+  PROP_0,
+  PROP_ENCODING,
+  PROP_VIDEOFPS,
+  PROP_EXTSUB_CURRENT_LANGUAGE,
+  PROP_IS_INTERNAL,
+  PROP_LANG_LIST
+
+};
+
+GST_DEBUG_CATEGORY_STATIC (gst_submux_debug);
+#define GST_CAT_DEFAULT gst_submux_debug
+#define _do_init(bla) \
+    GST_DEBUG_CATEGORY_INIT (gst_submux_debug, "submux", 0, "submux");
+////////////////////////////////////////////////////////
+//        Gstreamer Base Prototype                    //
+////////////////////////////////////////////////////////
+
+GST_BOILERPLATE_FULL(Gstsubmux, gst_submux, GstElement, GST_TYPE_ELEMENT, _do_init);
+
+#define GST_SUBMUX_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_SUBMUX, GstsubmuxPrivate))
+#define MAX_LANGUAGE 10
+static gint gst_submux_buffer_list_sorting (gconstpointer a, gconstpointer b);
+static gboolean gst_submux_create_pipelines(Gstsubmux *self,GstPad * pad);
+static GstPad*  gst_submux_request_new_pad (GstElement * element,
+       GstPadTemplate * templ, const gchar * req_name);
+static void gst_submux_release_pad (GstElement * element, GstPad * pad);
+static gchar* gst_submux_extract_data (Gstsubmux *submux);
+static gboolean gst_create_own_language_list (Gstsubmux *submux) ;
+static GstSubMuxFormat gst_submux_data_format_autodetect (gchar * match_str);
+static gpointer gst_submux_data_format_autodetect_regex_once (GstSubMuxRegex regtype);
+static gboolean gst_submux_format_autodetect (Gstsubmux * self);
+static void gst_submux_base_init(gpointer klass);
+static void gst_submux_class_init(GstsubmuxClass *klass);
+static GstStateChangeReturn gst_submux_change_state (GstElement * element, GstStateChange transition);
+static void gst_submux_init(Gstsubmux *submux, GstsubmuxClass *klass);
+static gboolean gst_submux_setcaps(GstPad *pad, GstCaps *caps);
+static GstFlowReturn gst_submux_chain (GstPad *pad, GstBuffer *buffer);
+static void gst_submux_dispose(GObject *object);
+static void gst_submux_loop (Gstsubmux * submux);
+static gboolean gst_submux_stream_init(GstSubmuxStream * stream);
+static void gst_submux_stream_deinit(GstSubmuxStream * stream,Gstsubmux * submux);
+static void gst_submux_on_new_buffer (GstElement *appsink, void *data);
+static gboolean gst_submux_handle_src_event (GstPad * pad, GstEvent * event);
+
+static gboolean gst_submux_handle_sink_event (GstPad * pad, GstEvent * event);
+////////////////////////////////////////////////////////
+//        Plugin Utility Prototype                    //
+////////////////////////////////////////////////////////
+static void gst_submux_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_submux_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static gboolean gst_submux_deinit_private_values(Gstsubmux *submux);
+static gchar *convert_to_utf8 (const gchar * str, gsize len, const gchar * encoding,
+    gsize * consumed, GError ** err, Gstsubmux * self);
+#define DEFAULT_ENCODING           NULL
+#define DEFAULT_CURRENT_LANGUAGE   NULL
+
+////////////////////////////////////////////////////////
+//        Gstreamer Base Functions                    //
+////////////////////////////////////////////////////////
+
+/*
+**
+**  Description : base init
+**  Params      : (1) instance of gclass
+**  return      : none
+**  Comments    : The following code registers templates for src and sink pad.
+**
+*/
+static void
+gst_submux_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(&gst_submux_sink_template));
+    gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&gst_submux_src_template));
+    gst_element_class_set_details(element_class, &gst_submux_plugin_details);
+}
+
+/*
+**
+**  Description    : Initilizes the Gstsubmux's class
+**  Params        : @ klass instance of submux plugin's class
+**  return        : None
+**  Comments    : Declaring properties and over-writing function pointers
+**
+*/
+static void
+gst_submux_class_init(GstsubmuxClass *klass)
+{
+    GstElementClass *gstelement_class = GST_ELEMENT_CLASS(klass);
+    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+    g_type_class_add_private (klass, sizeof (GstsubmuxPrivate));
+    gobject_class->set_property = gst_submux_set_property;
+    gobject_class->get_property = gst_submux_get_property;
+    g_object_class_install_property (gobject_class, PROP_ENCODING,
+        g_param_spec_string ("subtitle-encoding", "subtitle charset encoding",
+            "Encoding to assume if input subtitles are not in UTF-8 or any other "
+            "Unicode encoding. If not set, the GST_SUBTITLE_ENCODING environment "
+            "variable will be checked for an encoding to use. If that is not set "
+            "either, ISO-8859-15 will be assumed.", DEFAULT_ENCODING,
+            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property (gobject_class, PROP_VIDEOFPS,
+        gst_param_spec_fraction ("video-fps", "Video framerate",
+            "Framerate of the video stream. This is needed by some subtitle "
+            "formats to synchronize subtitles and video properly. If not set "
+            "and the subtitle format requires it subtitles may be out of sync.",
+            0, 1, G_MAXINT, 1, 24000, 1001,
+            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+    g_object_class_install_property (gobject_class, PROP_EXTSUB_CURRENT_LANGUAGE,
+          g_param_spec_string ("current-language", "Current language",
+                "Current language of the subtitle in external subtitle case.",
+                DEFAULT_CURRENT_LANGUAGE,
+                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+    g_object_class_install_property (gobject_class, PROP_IS_INTERNAL,
+          g_param_spec_boolean ("is-internal", "is internal",
+              "TRUE for internal subtitle case",
+              FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+    g_object_class_install_property (gobject_class, PROP_LANG_LIST,
+          g_param_spec_pointer ("lang-list", "language list", "List of languages selected/not selected",
+               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+    parent_class = g_type_class_peek_parent (klass);
+    gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_submux_request_new_pad);
+    gobject_class->dispose = GST_DEBUG_FUNCPTR(gst_submux_dispose);
+    gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_submux_change_state);
+    gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_submux_release_pad);
+}
+
+/*
+**
+**  Description    : Initilizes the submux element
+**  Params        : (1)instance of submux (2) instance of submux class
+**  return        : None
+**  Comments    : instantiate pads and add them to element, set pad calback functions
+**
+*/
+static void
+gst_submux_init(Gstsubmux *submux, GstsubmuxClass *klass)
+{
+  GST_DEBUG_OBJECT (submux, "Entering in init");
+  submux->priv = GST_SUBMUX_GET_PRIVATE(submux);
+  submux->srcpad = gst_pad_new_from_static_template(&gst_submux_src_template, "src");
+  gst_pad_set_event_function (submux->srcpad,
+            GST_DEBUG_FUNCPTR (gst_submux_handle_src_event));
+  submux->priv->first_buffer = FALSE;
+  gst_segment_init (&submux->segment, GST_FORMAT_TIME);
+  submux->flushing = FALSE;
+  submux->msl_streams = NULL;
+  submux->stop_loop = FALSE;
+  submux->need_segment = TRUE;
+  submux->pipeline_made = FALSE;
+  submux->external_sinkpad = FALSE;
+  submux->detected_encoding = NULL;
+  submux->encoding = NULL;
+  submux->seek_came = FALSE;
+  submux->sinkpads_count = 0;
+  submux->langlist_msg_posted = FALSE;
+  submux->cur_buf_array = NULL;
+  GST_DEBUG_OBJECT (submux, "Making flushing FALSE");
+  submux->priv->is_internal = FALSE;
+  submux->external_filepath = NULL;
+  gst_element_add_pad (GST_ELEMENT (submux), submux->srcpad);
+  GST_DEBUG_OBJECT (submux, "Exiting in init");
+}
+
+/*
+**
+**  Description    : for setting the property of submux
+**  return        : None
+**  Comments    : To set the various properties of submux
+**
+*/
+static void
+gst_submux_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  Gstsubmux *submux = GST_SUBMUX (object);
+  guint length = 0;
+  gint i = 0;
+  GstLangStruct *cur_language=NULL;
+  GstSubmuxStream *cur_stream = NULL;
+  GST_OBJECT_LOCK (submux);
+  length = g_list_length(submux->priv->lang_list);
+  switch (prop_id) {
+    case PROP_ENCODING:
+      g_free (submux->encoding);
+      submux->encoding = g_value_dup_string (value);
+      GST_DEBUG_OBJECT (submux, "subtitle encoding set to %s",
+          GST_STR_NULL (submux->encoding));
+      for(i = 0;i < length;i++) {
+        cur_stream = g_list_nth_data(submux->streams,i);
+        GST_DEBUG_OBJECT (submux, "setting the subtitle-encoding to %s", submux->encoding);
+        g_object_set (G_OBJECT (cur_stream->pipe_struc.parser), "subtitle-encoding", submux->encoding, NULL);
+      }
+      break;
+    case PROP_VIDEOFPS:
+    {
+      submux->fps_n = gst_value_get_fraction_numerator (value);
+      submux->fps_d = gst_value_get_fraction_denominator (value);
+      GST_DEBUG_OBJECT (submux, "video framerate set to %d/%d", submux->fps_n, submux->fps_d);
+      break;
+    }
+    case PROP_EXTSUB_CURRENT_LANGUAGE: {
+      for (i = 0; i < length; i++) {
+        cur_stream = g_list_nth_data(submux->streams, i);
+        cur_language = g_list_nth_data(submux->priv->lang_list, i);
+        GST_DEBUG_OBJECT (submux, "value of current-language key is %s", cur_language->language_key);
+        g_object_set (G_OBJECT (cur_stream->pipe_struc.parser), "current-language",
+                      cur_language->language_key, NULL);
+      }
+      gchar *dup = g_value_dup_string (value);
+      GST_DEBUG_OBJECT (submux, "Setting property to %s", dup);
+      g_free(dup);
+    }
+    break;
+    case PROP_IS_INTERNAL: {
+      submux->priv->is_internal = g_value_get_boolean (value);
+      GST_DEBUG_OBJECT (submux, "Setting the is_internal prop to %d", submux->priv->is_internal);
+      break;
+    }
+    case PROP_LANG_LIST: {
+      submux->priv->lang_list = (GList*) g_value_get_pointer (value);
+      GST_DEBUG_OBJECT (submux, "updating the languages list and length is %d", g_list_length (submux->priv->lang_list));
+      submux->msl_streams = g_list_copy (submux->priv->lang_list);
+
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (submux);
+}
+
+/*
+**
+**  Description    : for getting the property of submux
+**  return        : None
+**  Comments    : To get the various properties of submux in case called by MSL
+**
+*/
+static void
+gst_submux_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  Gstsubmux *submux = GST_SUBMUX (object);
+
+  GST_OBJECT_LOCK (submux);
+  switch (prop_id) {
+    case PROP_ENCODING:
+      g_value_set_string (value, submux->encoding);
+      break;
+    case PROP_VIDEOFPS:
+      gst_value_set_fraction (value, submux->fps_n, submux->fps_d);
+      break;
+    case PROP_EXTSUB_CURRENT_LANGUAGE:
+      GST_DEBUG_OBJECT (submux, "Getting the current language");
+      break;
+    case PROP_IS_INTERNAL: {
+      g_value_set_boolean(value,submux->priv->is_internal);
+      break;
+    }
+    case PROP_LANG_LIST: {
+      g_value_set_pointer(value,(gpointer)(submux->priv->lang_list));
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (submux);
+}
+
+static void
+gst_submux_dispose (GObject *object)
+{
+  Gstsubmux *submux = GST_SUBMUX(object);
+  int i = 0;
+  gchar *pad_name = gst_pad_get_name (submux->srcpad);
+  if (submux && GST_PAD_TASK(submux->srcpad)) {
+    GST_INFO_OBJECT (submux, "Stopping pad task : %s", pad_name);
+    GST_DEBUG_OBJECT (submux, "Stopping pad task : on src pad %p", submux->srcpad);
+    gst_pad_stop_task (submux->srcpad);
+    GST_INFO_OBJECT (submux, "stopped pad task : %s", pad_name);
+  }
+  g_free(pad_name);
+  if (submux->srcpad) {
+    gst_element_remove_pad (GST_ELEMENT_CAST (submux), submux->srcpad);
+    submux->srcpad = NULL;
+  }
+  if (submux->priv->is_internal) {
+    for (i = 0; i < (submux->sinkpads_count); i++){
+      gst_submux_stream_deinit (g_list_nth_data (submux->streams, i), submux);
+    }
+  } else {
+    for (i = 0; i < g_list_length (submux->priv->lang_list); i++) {
+      gst_submux_stream_deinit (g_list_nth_data (submux->streams, i), submux);
+    }
+  }
+  gst_submux_deinit_private_values (submux);
+
+  GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
+  GST_DEBUG_OBJECT (submux, "Returning from finalize");
+}
+
+static void
+gst_submux_stop (Gstsubmux* submux)
+{
+  GstSubmuxStream *new_stream = NULL;
+  guint i = 0;
+  submux->stop_loop = TRUE;
+  GST_INFO_OBJECT (submux, "stopping the loop");
+  if (submux->priv->is_internal) {
+    for (i = 0; i < (submux->sinkpads_count); i++) {
+      new_stream =  g_list_nth_data (submux->streams, i);
+      if (new_stream) {
+        g_mutex_lock (new_stream->queue_lock);
+        g_cond_signal (new_stream->queue_empty);
+        g_mutex_unlock (new_stream->queue_lock);
+      }
+    }
+  } else {
+    for (i = 0; i < g_list_length (submux->priv->lang_list); i++) {
+      new_stream =  g_list_nth_data (submux->streams, i);
+      if (new_stream) {
+        g_mutex_lock (new_stream->queue_lock);
+        g_cond_signal (new_stream->queue_empty);
+        g_mutex_unlock (new_stream->queue_lock);
+      }
+    }
+  }
+}
+
+static GstStateChangeReturn
+gst_submux_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret;
+  Gstsubmux *submux = GST_SUBMUX (element);
+  gboolean bret = FALSE;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      GST_INFO_OBJECT (submux,"PAUSED->PLAYING");
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      GST_INFO_OBJECT (submux,"PAUSED->READY");
+      gst_submux_stop (submux);
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      GST_INFO_OBJECT (submux,"PLAYING->PAUSED");
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      GST_INFO_OBJECT (submux,"PAUSED->READY");
+      if(submux->msl_streams) {
+        g_list_free(submux->msl_streams);
+        submux->msl_streams = NULL;
+      }
+      if (submux->priv->lang_list && !submux->priv->is_internal) {
+        g_list_free (submux->priv->lang_list);
+        submux->priv->lang_list = NULL;
+      }
+      if (submux->external_filepath) {
+        g_free (submux->external_filepath);
+        submux->external_filepath = NULL;
+      }
+      GST_WARNING_OBJECT(submux,"stopping has been called ...Moved after change_state");
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      GST_INFO_OBJECT (submux,"READY->NULL");
+      break;
+    default:
+      break;
+  }
+  return ret;
+}
+
+/*
+**
+**  Description    : Setting the caps on sink pad based on upstream element's src pad
+**  Params        : (1) GstPad to set the capabilities of
+**                   (2) caps to be set
+**  return        : TRUE on success
+**  Comments    : this function handles the link with other elements
+**
+*/
+static gboolean
+gst_submux_setcaps (GstPad *pad, GstCaps *caps)
+{
+  return TRUE;
+}
+
+/*extracting data for file format detection*/
+static gchar* gst_submux_extract_data (Gstsubmux *submux){
+  gchar * file_path_type = NULL;
+  gchar * file_path = NULL;
+  gchar * temp_path = NULL;
+  gchar  *line = NULL;
+  gboolean is_converted = FALSE;
+  gchar *converted = NULL;
+  FILE  * fp = NULL;
+  guint charCount = 0;
+  GError *err = NULL;
+  gsize * consumed = NULL;
+
+  GstQuery *cquery;
+  GstStructure *structure;
+  const GValue *value;
+  GstPad *sinkpad = (GstPad *)g_list_nth_data (submux->sinkpad, 0);
+  structure = gst_structure_new ("FileSrcURI",
+                                 "file-uri", G_TYPE_STRING, NULL, NULL);
+
+  cquery = gst_query_new_application (GST_QUERY_CUSTOM, structure);
+
+  if (!gst_pad_peer_query (sinkpad, cquery))
+  {
+    GST_ERROR_OBJECT (submux, "Failed to query SMI file path");
+    gst_query_unref (cquery);
+    return NULL;
+  }
+  structure = gst_query_get_structure (cquery);
+  value = gst_structure_get_value (structure, "file-uri");
+  file_path = g_strdup (g_value_get_string (value));
+
+  if (file_path == NULL){
+    GST_ERROR_OBJECT (submux, "Could not parse the SMI file path");
+    gst_query_unref (cquery);
+    return NULL;
+  }
+
+  gst_query_unref (cquery);
+  temp_path = file_path;
+  GST_INFO_OBJECT (submux, "File path comes as %s", file_path);
+
+  file_path_type = g_strndup ((gchar *) file_path, 4);
+  GST_INFO_OBJECT (submux, "Received file path by query = %s, %s", file_path, file_path_type);
+  if (!g_strcmp0(file_path_type, "file")){
+    file_path += 7;
+    GST_INFO_OBJECT (submux, "File path comes as %s", file_path);
+
+    fp = fopen (file_path, "r");
+    if (!fp){
+      GST_ERROR_OBJECT (submux, "Failed to open file");
+      g_free(file_path_type);
+      g_free(temp_path);
+      return NULL;
+    }
+  } else {
+    GST_ERROR_OBJECT (submux, "File is not local");
+    g_free(file_path_type);
+    g_free(temp_path);
+    return NULL;
+  }
+  line = (gchar*)g_malloc (2049);
+  charCount = fread (line, sizeof(char), 2048, fp);
+  line[charCount] = '\0';
+  if (submux->encoding && strcmp (submux->encoding, "UTF-8"))
+    converted = convert_to_utf8 (line, charCount, submux->encoding, consumed, &err, submux);
+
+  if (converted)
+  {
+    GST_INFO("returned from conversion and length of converted string is[%d]", strlen(converted));
+    is_converted = TRUE;
+  }
+  if (!charCount) {
+    GST_WARNING_OBJECT (submux, "fread returned zero bytes");
+    fclose (fp);
+    g_free(file_path_type);
+    g_free(temp_path);
+    if(is_converted) {
+      g_free(converted);
+    }
+    g_free(line);
+    return NULL;
+  }
+  g_free(file_path_type);
+  g_free(temp_path);
+  fclose (fp);
+  if(is_converted) {
+    return converted;
+  }
+  return line;
+}
+
+static gpointer
+gst_submux_data_format_autodetect_regex_once (GstSubMuxRegex regtype)
+{
+  gpointer result = NULL;
+  GError *gerr = NULL;
+  switch (regtype) {
+    case GST_SUB_PARSE_REGEX_MDVDSUB:
+      result =
+          (gpointer) g_regex_new ("^\\{[0-9]+\\}\\{[0-9]+\\}",
+          G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &gerr);
+      if (result == NULL) {
+        g_warning ("Compilation of mdvd regex failed: %s", gerr->message);
+        g_error_free (gerr);
+      }
+      break;
+    case GST_SUB_PARSE_REGEX_SUBRIP:
+      result = (gpointer) g_regex_new ("^ {0,3}[ 0-9]{1,4}\\s*(\x0d)?\x0a"
+          " ?[0-9]{1,2}: ?[0-9]{1,2}: ?[0-9]{1,2}[,.] {0,2}[0-9]{1,3}"
+          " +--> +[0-9]{1,2}: ?[0-9]{1,2}: ?[0-9]{1,2}[,.] {0,2}[0-9]{1,2}",
+          G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &gerr);
+      if (result == NULL) {
+        g_warning ("Compilation of subrip regex failed: %s", gerr->message);
+        g_error_free (gerr);
+      }
+      break;
+    case GST_SUB_PARSE_REGEX_DKS:
+      result = (gpointer) g_regex_new ("^\\[[0-9]+:[0-9]+:[0-9]+\\].*",
+          G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &gerr);
+      if (result == NULL) {
+        g_warning ("Compilation of dks regex failed: %s", gerr->message);
+        g_error_free (gerr);
+      }
+      break;
+    default:
+      GST_WARNING ("Trying to allocate regex of unknown type %u", regtype);
+  }
+  return result;
+}
+
+static GstSubMuxFormat
+gst_submux_data_format_autodetect (gchar * match_str)
+{
+  guint n1, n2, n3;
+
+  static GOnce mdvd_rx_once = G_ONCE_INIT;
+  static GOnce subrip_rx_once = G_ONCE_INIT;
+  static GOnce dks_rx_once = G_ONCE_INIT;
+
+  GRegex *mdvd_grx;
+  GRegex *subrip_grx;
+  GRegex *dks_grx;
+
+  g_once (&mdvd_rx_once,
+      (GThreadFunc) gst_submux_data_format_autodetect_regex_once,
+      (gpointer) GST_SUB_PARSE_REGEX_MDVDSUB);
+  g_once (&subrip_rx_once,
+      (GThreadFunc) gst_submux_data_format_autodetect_regex_once,
+      (gpointer) GST_SUB_PARSE_REGEX_SUBRIP);
+  g_once (&dks_rx_once,
+      (GThreadFunc) gst_submux_data_format_autodetect_regex_once,
+      (gpointer) GST_SUB_PARSE_REGEX_DKS);
+
+  mdvd_grx = (GRegex *) mdvd_rx_once.retval;
+  subrip_grx = (GRegex *) subrip_rx_once.retval;
+  dks_grx = (GRegex *) dks_rx_once.retval;
+
+  if (g_regex_match (mdvd_grx, match_str, 0, NULL) == TRUE) {
+    GST_LOG ("MicroDVD (frame based) format detected");
+    return GST_SUB_PARSE_FORMAT_MDVDSUB;
+  }
+  if (g_regex_match (subrip_grx, match_str, 0, NULL) == TRUE) {
+    GST_LOG ("SubRip (time based) format detected");
+    return GST_SUB_PARSE_FORMAT_SUBRIP;
+  }
+  if (g_regex_match (dks_grx, match_str, 0, NULL) == TRUE) {
+    GST_LOG ("DKS (time based) format detected");
+    return GST_SUB_PARSE_FORMAT_DKS;
+  }
+
+  if (!strncmp (match_str, "FORMAT=TIME", 11)) {
+    GST_LOG ("MPSub (time based) format detected");
+    return GST_SUB_PARSE_FORMAT_MPSUB;
+  }
+  if (strstr (match_str, "<SAMI>") != NULL ||
+      strstr (match_str, "<sami>") != NULL) {
+    GST_LOG ("SAMI (time based) format detected");
+    return GST_SUB_PARSE_FORMAT_SAMI;
+  }
+  /* we're boldly assuming the first subtitle appears within the first hour */
+  if (sscanf (match_str, "0:%02u:%02u:", &n1, &n2) == 2 ||
+      sscanf (match_str, "0:%02u:%02u=", &n1, &n2) == 2 ||
+      sscanf (match_str, "00:%02u:%02u:", &n1, &n2) == 2 ||
+      sscanf (match_str, "00:%02u:%02u=", &n1, &n2) == 2 ||
+      sscanf (match_str, "00:%02u:%02u,%u=", &n1, &n2, &n3) == 3) {
+    GST_LOG ("TMPlayer (time based) format detected");
+    return GST_SUB_PARSE_FORMAT_TMPLAYER;
+  }
+  if (sscanf (match_str, "[%u][%u]", &n1, &n2) == 2) {
+    GST_LOG ("MPL2 (time based) format detected");
+    return GST_SUB_PARSE_FORMAT_MPL2;
+  }
+  if (strstr (match_str, "[INFORMATION]") != NULL) {
+    GST_LOG ("SubViewer (time based) format detected");
+    return GST_SUB_PARSE_FORMAT_SUBVIEWER;
+  }
+  if (strstr (match_str, "{QTtext}") != NULL) {
+    GST_LOG ("QTtext (time based) format detected");
+    return GST_SUB_PARSE_FORMAT_QTTEXT;
+  }
+
+  GST_WARNING ("no subtitle format detected");
+  return GST_SUB_PARSE_FORMAT_UNKNOWN;
+}
+
+/*checking the type of subtitle*/
+static gboolean
+gst_submux_format_autodetect (Gstsubmux *self)
+{
+  gchar *data;
+  GstSubMuxFormat format;
+  gchar * line = NULL;
+  if (self->priv->is_internal) {
+    GST_DEBUG_OBJECT (self, "File is of internal type");
+    return TRUE;
+  }
+  line = gst_submux_extract_data (self);
+  if (!line)
+    return FALSE;
+  if (strlen (line) < 30) {
+    GST_WARNING_OBJECT (self, "File too small to be a subtitles file");
+    g_free(line);
+    return FALSE;
+  }
+
+  data = g_strndup (line, 35);
+  format = gst_submux_data_format_autodetect (data);
+  g_free (data);
+
+  self->priv->parser_type = format;
+  g_free(line);
+
+  return TRUE;
+}
+
+/*to validate the number of languages in case of sami files*/
+static gboolean
+gst_calculate_number_languages(Gstsubmux *self) {
+  gchar* text=NULL;
+  gchar *start = NULL;
+  gchar *end = NULL;
+  gint count = 0;
+  gchar* found = NULL;
+  gchar * name_temp = NULL;
+  int i = 0, j = 0;
+
+  GST_DEBUG_OBJECT (self, "Entering in language number");
+
+  if ((self->priv->parser_type != GST_SUB_PARSE_FORMAT_SAMI) || self->priv->is_internal)
+    return TRUE;
+
+  text = gst_submux_extract_data (self);
+  start = g_strstr_len (text, strlen (text), "!--");
+  if (!start) {
+    GST_ERROR_OBJECT (self, "Could not found the language start code in smi file");
+    return gst_create_own_language_list(self);
+  }
+  end =  g_strstr_len (start, strlen (start), "-->");
+  if (!end){
+    GST_ERROR_OBJECT (self, "Could not found the language end code in smi file");
+    goto error;
+  }
+
+  found = start + 1;
+
+  while (TRUE) {
+    found = (gchar*)strcasestr (found, "lang");
+    if (!found)
+       break;
+    found++;
+    count++;
+  }
+
+  if (!count)
+  {
+    return gst_create_own_language_list(self);
+  }
+
+  for (i = 0; i < count; i++) {
+    gchar *attr_name = NULL, *attr_value = NULL;
+    GstLangStruct *new = NULL;
+
+    start = (gchar*)strcasestr (start, "lang:");
+    attr_value = (gchar*)malloc (3);
+    if (!attr_value) {
+      GST_ERROR_OBJECT (self, "memory could not be allocated through malloc call");
+      goto error;
+    }
+    start = start + 5;
+    strncpy (attr_value, start, 2);
+    attr_value[2] = '\0';
+    GST_DEBUG_OBJECT (self, "Language value comes as %s", attr_value);
+    name_temp = start;
+    while (TRUE) {
+      if (*name_temp == '{') {
+        int character_count = 0;
+        while (TRUE) {
+          name_temp--;
+
+          if (*name_temp == '.') {
+            attr_name = (gchar*) malloc (character_count + 1);
+            break;
+          } else if (*name_temp != ' ')
+             character_count++;
+        }
+        break;
+      }
+      name_temp--;
+    }
+    if (!attr_name) {
+      GST_ERROR_OBJECT (self, "Could not find the languages field in the file");
+      free(attr_value);
+      goto error;
+    }
+    name_temp++;
+    for (j = 0; *(name_temp + j) != ' '; j++) {
+      attr_name[j] = *(name_temp + j);
+    }
+    attr_name[j] = '\0';
+    new = g_new0 (GstLangStruct, 1);
+    if (attr_value) {
+      new->language_code = g_strdup(attr_value);
+    }
+    if (attr_name) {
+      new->language_key = g_strdup(attr_name);
+    }
+    free (attr_name);
+    free (attr_value);
+    self->priv->lang_list = g_list_append (self->priv->lang_list, new);
+  }
+  g_free(text);
+  return TRUE;
+error:
+  g_free(text);
+  return FALSE;
+}
+
+/*to initialize stream*/
+static gboolean gst_submux_stream_init(GstSubmuxStream * stream)
+{
+  stream->duration = 0;
+  stream->need_segment = TRUE;
+  stream->flushing = FALSE;
+  stream->eos_sent = FALSE;
+  stream->eos_came = FALSE;
+  stream->discont_came = FALSE;
+  stream->eos_ts = -1;
+  stream->last_ts = -1;
+  stream->queue = g_queue_new ();
+  stream->queue_empty = g_cond_new ();
+  stream->queue_lock = g_mutex_new ();
+  stream->flush_done = FALSE;
+  return TRUE;
+}
+
+/*to create pipelines according to internal and external subtitle*/
+gboolean gst_submux_create_pipelines(Gstsubmux *self, GstPad * pad)
+{
+  int i = 0;
+  GstStateChangeReturn ret;
+  GstSubmuxStream *new_stream;
+  guint length = 0;
+
+  if (!self->priv->is_internal) {
+    GstLangStruct *cur_language=NULL;
+
+    GST_DEBUG_OBJECT (self, "creating the pipeline for external pipeline");
+    if (self->priv->parser_type == GST_SUB_PARSE_FORMAT_SAMI) {
+      if (!self->priv->lang_list) {
+        GST_ERROR_OBJECT(self, "failed to get the lang list");
+        return FALSE;
+      }
+      length = g_list_length (self->priv->lang_list);
+    } else {
+      length = 1;
+    }
+
+    GST_DEBUG_OBJECT (self, "number of tentative languages present are %d", length);
+
+    for (i = 0; i < length; i++) {
+      new_stream = g_new0 (GstSubmuxStream, 1);
+      if (!gst_submux_stream_init(new_stream)) {
+        GST_ERROR_OBJECT (self, "stream init is failed");
+        return FALSE;
+      }
+      GST_DEBUG_OBJECT (self, "stream init has been done for stream[%d]", i);
+
+      new_stream->pipe_struc.pipe = gst_pipeline_new ("subtitle-pipeline");
+      if (!new_stream->pipe_struc.pipe) {
+        GST_ERROR_OBJECT (self, "failed to create pipeline");
+        return FALSE;
+      }
+      GST_DEBUG_OBJECT (self, "creating appsrc");
+
+      /* creating source element */
+      new_stream->pipe_struc.appsrc = gst_element_factory_make ("appsrc", "pipe_appsrc");
+      if (!new_stream->pipe_struc.appsrc) {
+        GST_ERROR_OBJECT (self, "failed to create appsrc");
+        return FALSE;
+      }
+
+      g_object_set (G_OBJECT (new_stream->pipe_struc.appsrc), "block", 1, NULL);
+      g_object_set (G_OBJECT (new_stream->pipe_struc.appsrc), "max-bytes", (guint64)1, NULL);
+      /* create sink element */
+      new_stream->pipe_struc.appsink =  gst_element_factory_make ("appsink", "pipe_appsink");
+      if (!new_stream->pipe_struc.appsink) {
+        GST_ERROR_OBJECT (self, "failed to create appsink");
+        return FALSE;
+      }
+      g_object_set (G_OBJECT (new_stream->pipe_struc.appsink), "sync", FALSE, "emit-signals", TRUE, NULL);
+      g_object_set(G_OBJECT (new_stream->pipe_struc.appsrc),"emit-signals", TRUE, NULL);
+
+
+      /* create parsing element */
+      new_stream->pipe_struc.parser = gst_element_factory_make("subparse","pipe_parser");
+      if (!new_stream->pipe_struc.parser) {
+        GST_ERROR_OBJECT (self, "failed to create parser");
+        return FALSE;
+      }
+      if (self->priv->parser_type == GST_SUB_PARSE_FORMAT_SAMI) {
+        cur_language = g_list_nth_data(self->priv->lang_list, i);
+        g_object_set (G_OBJECT (new_stream->pipe_struc.parser), "current-language",
+                              cur_language->language_key, NULL);
+      }
+      GST_DEBUG_OBJECT (self, "value of subtitle-encoding  is %s", self->encoding);
+      g_object_set (G_OBJECT (new_stream->pipe_struc.parser), "subtitle-encoding", self->encoding, NULL);
+      g_object_set (G_OBJECT (new_stream->pipe_struc.appsrc), "stream-type",0,"format",GST_FORMAT_TIME, NULL);
+      gst_bin_add_many (GST_BIN ( new_stream->pipe_struc.pipe), new_stream->pipe_struc.appsink, new_stream->pipe_struc.appsrc,new_stream->pipe_struc.parser, NULL);
+      if (!gst_element_link_many (new_stream->pipe_struc.appsrc, new_stream->pipe_struc.parser,new_stream->pipe_struc.appsink, NULL)) {
+        GST_ERROR_OBJECT (self, "failed to link elements");
+        return FALSE;
+      }
+
+      GST_DEBUG_OBJECT (self, "reached here and linking successful");
+
+      ret = gst_element_set_state (new_stream->pipe_struc.pipe, GST_STATE_PLAYING);
+      if (ret == GST_STATE_CHANGE_FAILURE) {
+        GST_ERROR_OBJECT (self, "set_state failed...");
+        return FALSE;
+      }
+      GST_DEBUG_OBJECT (self, "state has been changed succesfully");
+      self->streams = g_list_append(self->streams, new_stream);
+      self->priv->stream_count++;
+      g_signal_connect (new_stream->pipe_struc.appsink, "new-buffer",  G_CALLBACK (gst_submux_on_new_buffer), g_list_nth_data(self->streams,i) );
+    }
+  } else {
+    length = self->sinkpads_count;
+    for (i = 0; i < length; i++) {
+      new_stream = g_new0 (GstSubmuxStream, 1);
+      if (!gst_submux_stream_init (new_stream)) {
+        GST_ERROR_OBJECT (self, "stream init is failed");
+        return FALSE;
+     }
+
+      self->streams=g_list_append(self->streams,new_stream);
+      self->priv->stream_count++;
+    }
+    self->pipeline_made  = TRUE;
+  }
+
+  self->cur_buf_array = g_malloc0 (self->priv->stream_count * (sizeof (GstBuffer *)));
+  if (!self->cur_buf_array) {
+    GST_ERROR_OBJECT (self, "failed to allocate memory..");
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/* call back on recieving the new buffer in appsink pad */
+static void
+gst_submux_on_new_buffer (GstElement *appsink, void *data)
+{
+  GstSubmuxStream *stream = (GstSubmuxStream  *)data;
+  GstBuffer *inbuf = NULL;
+
+  if (!stream) {
+    GST_WARNING("Stream not available...");
+    return;
+  }
+  g_mutex_lock (stream->queue_lock);
+  inbuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
+  if (!inbuf) {
+    GST_WARNING_OBJECT (stream, "Input buffer not available...");
+    g_mutex_unlock (stream->queue_lock);
+    return;
+  }
+  if(stream->eos_ts == -1) {
+    if (!strcmp ((const char*)GST_BUFFER_DATA (inbuf), "eos") && GST_BUFFER_FLAG_IS_SET(inbuf,GST_BUFFER_FLAG_GAP)){
+      stream->eos_ts = stream->last_ts;
+      if (stream->eos_ts <= stream->seek_ts) {
+        g_queue_push_tail (stream->queue, inbuf);
+        g_cond_signal (stream->queue_empty);
+        g_mutex_unlock (stream->queue_lock);
+        GST_INFO_OBJECT (stream, "signaling queue empty signal as we are seeking beyond last subtitle");
+        return;
+      }
+      gst_buffer_unref(inbuf);
+    } else {
+      stream->last_ts = GST_BUFFER_DURATION(inbuf) + GST_BUFFER_TIMESTAMP(inbuf);
+    }
+  } else if (stream->eos_ts <= stream->seek_ts) {
+    gst_buffer_unref(inbuf);
+    GstBuffer *buf = gst_buffer_new_and_alloc (3 + 1);
+    GST_DEBUG_OBJECT(stream, "sending EOS buffer to chain\n");
+    GST_DEBUG_OBJECT (stream, "EOS. Pushing remaining text (if any)");
+    GST_BUFFER_DATA (buf)[0] = 'e';
+    GST_BUFFER_DATA (buf)[1] = 'o';
+    GST_BUFFER_DATA (buf)[2] = 's';
+    GST_BUFFER_DATA (buf)[3] = '\0';
+    /* play it safe */
+    GST_BUFFER_SIZE (buf) = 3;
+    GST_BUFFER_FLAG_SET(buf,GST_BUFFER_FLAG_GAP);
+    g_queue_push_tail (stream->queue, buf);
+    g_cond_signal (stream->queue_empty);
+    g_mutex_unlock (stream->queue_lock);
+    GST_INFO_OBJECT (stream,"signaling queue empty signal as we are seeking beyond last subtitle");
+    return;
+  }
+  if (!stream->discont_came) {
+    stream->discont_came = GST_BUFFER_IS_DISCONT (inbuf);
+    if (stream->discont_came) {
+      GST_DEBUG_OBJECT (stream, "first buffer with discont on new_buffer for stream with ts = %"
+                        GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(inbuf)),
+                        GST_TIME_ARGS(GST_BUFFER_DURATION(inbuf)));
+    }
+  }
+
+  if (!stream->discont_came) {
+    GST_DEBUG_OBJECT (stream, "rejecting the buffer in appsink on new_buffer for stream with ts = %"
+                      GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(inbuf)),
+                      GST_TIME_ARGS(GST_BUFFER_DURATION(inbuf)));
+    gst_buffer_unref(inbuf);
+    g_mutex_unlock (stream->queue_lock);
+    return;
+  }
+  g_queue_push_tail (stream->queue, inbuf);
+  g_cond_signal (stream->queue_empty);
+  g_mutex_unlock (stream->queue_lock);
+  GST_DEBUG_OBJECT (stream, "signaling queue empty signal");
+  return;
+}
+
+gchar *
+convert_to_utf8 (const gchar * str, gsize len, const gchar * encoding,
+    gsize * consumed, GError ** err, Gstsubmux * self)
+{
+  gchar *ret = NULL;
+
+  /* The char cast is necessary in glib < 2.24 */
+  ret =
+      g_convert_with_fallback (str, len, "UTF-8", encoding, (char *) "*",
+      consumed, NULL, err);
+
+  if (ret == NULL)
+  {
+    GST_DEBUG_OBJECT (self, "g_convert_with_fallback returns NULL");
+    return ret;
+  }
+
+  /* + 3 to skip UTF-8 BOM if it was added */
+  len = strlen (ret);
+  if (len >= 3 && (guint8) ret[0] == 0xEF && (guint8) ret[1] == 0xBB
+      && (guint8) ret[2] == 0xBF)
+    g_memmove (ret, ret + 3, len + 1 - 3);
+
+  return ret;
+}
+
+static gchar *
+detect_encoding (const gchar * str, gsize len)
+{
+  if (len >= 3 && (guint8) str[0] == 0xEF && (guint8) str[1] == 0xBB
+      && (guint8) str[2] == 0xBF)
+    return g_strdup ("UTF-8");
+
+  if (len >= 2 && (guint8) str[0] == 0xFE && (guint8) str[1] == 0xFF)
+    return g_strdup ("UTF-16BE");
+
+  if (len >= 2 && (guint8) str[0] == 0xFF && (guint8) str[1] == 0xFE)
+    return g_strdup ("UTF-16LE");
+
+  if (len >= 4 && (guint8) str[0] == 0x00 && (guint8) str[1] == 0x00
+      && (guint8) str[2] == 0xFE && (guint8) str[3] == 0xFF)
+    return g_strdup ("UTF-32BE");
+
+  if (len >= 4 && (guint8) str[0] == 0xFF && (guint8) str[1] == 0xFE
+      && (guint8) str[2] == 0x00 && (guint8) str[3] == 0x00)
+    return g_strdup ("UTF-32LE");
+
+  return NULL;
+}
+
+/* If language list is not present in smi file, check the body and create our own list */
+static gboolean
+gst_create_own_language_list (Gstsubmux *self)
+{
+  gchar * file_path_type = NULL;
+  gchar * temp_path = NULL;
+  gchar * file_path = NULL;
+  gsize * consumed = NULL;
+  guint keyCount = 0;
+  GError *err = NULL;
+  GstPad *sinkpad = (GstPad *) g_list_nth_data(self->sinkpad, 0);
+  GstQuery *cquery;
+  GstStructure *structure;
+  const GValue *value;
+  gchar* langkey[MAX_LANG];
+  gint langKey_length[MAX_LANG];
+  FILE *fp=NULL;
+  gint i=0;
+  structure = gst_structure_new ("FileSrcURI", "file-uri", G_TYPE_STRING, NULL, NULL);
+
+  cquery = gst_query_new_application (GST_QUERY_CUSTOM, structure);
+
+  if (!gst_pad_peer_query (sinkpad, cquery)) {
+    GST_ERROR_OBJECT (self, "Failed to query SMI file path");
+    gst_query_unref (cquery);
+    return FALSE;
+  }
+  structure = gst_query_get_structure (cquery);
+  value = gst_structure_get_value (structure, "file-uri");
+  file_path = g_strdup (g_value_get_string (value));
+
+  if (file_path == NULL){
+    GST_ERROR_OBJECT (self, "Could not parse the SMI file path");
+    gst_query_unref (cquery);
+    return FALSE;
+  }
+  gst_query_unref (cquery);
+  temp_path = file_path;
+  GST_INFO_OBJECT (self, "File path comes as %s", file_path);
+
+  file_path_type = g_strndup ((gchar *) file_path, 4);
+  GST_INFO_OBJECT (self, "Received file path by query = %s, %s", file_path, file_path_type);
+  if (!g_strcmp0(file_path_type, "file")){
+    file_path += 7;
+    GST_INFO_OBJECT (self, "File path comes as %s", file_path);
+
+    fp = fopen (file_path, "r");
+    if (!fp){
+      GST_ERROR_OBJECT (self, "Failed to open file");
+      g_free(temp_path);
+      g_free(file_path_type);
+      return FALSE;
+    }
+  }
+  for( i=0;i<MAX_LANG;i++){
+    langkey[i]=NULL;
+    langKey_length[i]=0;
+  }
+  gboolean lang_found= FALSE;
+  while (!feof (fp) ){
+    gchar line[1025];
+    guint charCount = 0;
+    gboolean conversion = TRUE;
+    gchar *result = NULL;
+    gchar *con_temp = NULL;
+    gchar *delimiter = NULL;
+    gchar *temp = NULL;
+    guint keyLength = 0;
+
+    charCount = fread (line, sizeof(char), 1024, fp);
+    line[charCount] = '\0';
+    if (!charCount) {
+      GST_WARNING_OBJECT (self, "fread returned zero bytes");
+      continue;
+    }
+    GST_DEBUG_OBJECT (self, " Read charCount %d bytes Successfully",charCount);
+    GST_DEBUG_OBJECT (self, "value of detected encoding is %s and self encoding is %s",
+        self->detected_encoding,self->encoding);
+    if (self->detected_encoding && strcmp (self->detected_encoding, "UTF-8") && conversion){
+      result = convert_to_utf8 (line, charCount, self->detected_encoding, consumed, &err, self);
+      GST_DEBUG_OBJECT (self, " Converted convert_to_utf8  result %d ",result);
+    }
+    if (result == NULL) {
+      result = line;
+      conversion =  FALSE;
+    }
+    con_temp =  result;
+    temp = con_temp;
+
+    while (con_temp){
+      gchar* tempKey = NULL;
+      guint i = 0;
+
+      con_temp =  strcasestr(con_temp,"class=");
+      if(con_temp)
+        delimiter =  strcasestr(con_temp, ">");
+      GST_DEBUG_OBJECT (self, " Delimiter ...Entering if %s",con_temp);
+      if (con_temp && (delimiter!=NULL)){
+        gchar* tempChar = con_temp + 6;
+        GST_DEBUG_OBJECT (self, "Has class= reading string %s",tempChar);
+        GST_DEBUG_OBJECT (self, "Has class= ");
+        while (*tempChar != '>'){
+          keyLength++;
+          tempChar++;
+          GST_DEBUG_OBJECT (self, " keyLength %d tempChar %c",keyLength,*tempChar);
+        }
+        GST_DEBUG_OBJECT (self, " keyLength  %d",keyLength);
+        tempChar -= keyLength;
+        tempKey = (gchar*) g_malloc (keyLength + 1);
+        if(!tempKey){
+          GST_DEBUG_OBJECT (self, "Error 1");
+          goto error;
+        }
+        gchar* temp1 =tempKey;
+        GST_DEBUG_OBJECT (self, "tempChar %s  keyLength  %d",tempChar,keyLength);
+        while (*tempChar != '>'){
+          *tempKey = *tempChar;
+          tempKey++;
+          tempChar++;
+        }
+        tempKey =temp1;
+        tempKey[keyLength]='\0';
+        GST_DEBUG_OBJECT (self, "tempKey %s  keyLength %d keyCount %d",tempKey,keyLength,keyCount);
+        int k =0;
+        for (k = 0; k < keyCount; k++){
+          if(langkey[k]){
+            if (!strcasecmp (tempKey,langkey[k]))
+            {
+              GST_DEBUG_OBJECT (self, "Has the key already so breaking..Entry %d tempKey %s langkey[i] %s ",k,tempKey,langkey[k]);
+              lang_found = TRUE;
+              break;
+            }
+          }
+        }
+        if(lang_found == FALSE){
+          langkey[keyCount] = g_strdup (tempKey);
+          langKey_length[keyCount]=keyLength;
+          keyCount++;
+        }
+        lang_found =FALSE;
+        keyLength =0;
+        if(tempKey){
+          g_free(tempKey);
+          tempKey=NULL;
+        }
+      } else {
+        keyLength =0;
+        lang_found =FALSE;
+        break;
+      }
+      con_temp+=6;
+      GST_DEBUG_OBJECT (self, " ..increment con_temp %s",con_temp);
+    }
+  }
+  GST_DEBUG_OBJECT (self, " At end keyCount no of langs is %d ",keyCount);
+  for(i=0;i<keyCount;i++) {
+    if(langkey[i]) {
+      GstLangStruct *new = g_new0 (GstLangStruct, 1);
+      GST_DEBUG_OBJECT (self, "Adding ign case to the langKey keyCount %d and lang %s ",i, langkey[i]);
+      new->language_code = (gchar*)malloc (3);
+      if(!(new->language_code)){
+        GST_DEBUG_OBJECT (self, " .Error 2");
+        goto error;
+      }
+      gchar *attr_val=new->language_code ;
+      strncpy (attr_val, "un", 2);
+      attr_val[2]='\0';
+
+      new->language_key = g_strdup(langKey_length[i]);
+      self->priv->lang_list = g_list_append (self->priv->lang_list, new);
+      GST_DEBUG_OBJECT (self, " new...Successfull");
+      g_free(langkey[i]);
+    }
+  }
+  if (fp) {
+    g_free(temp_path);
+    g_free(file_path_type);
+    fclose(fp);
+    fp = NULL;
+  }
+  return TRUE;
+error:
+  GST_DEBUG_OBJECT (self, " In Error");
+  if (fp) {
+    g_free(temp_path);
+    g_free(file_path_type);
+    fclose(fp);
+    fp = NULL;
+  }
+  return FALSE;
+}
+
+gboolean
+validate_langlist_body(GList * lang_list, Gstsubmux * self){
+  gchar * file_path_type = NULL;
+  gchar * file_path = NULL;
+  gchar   line[1025];
+  FILE  * fp = NULL;
+  guint i = 0, found_count = 0,k = 0;
+  const guint list_len = g_list_length(lang_list);
+  gboolean counter[MAX_LANGUAGE];
+  GstPad  *sinkpad = NULL;
+  struct LangStruct
+  {
+      gchar *language_code;
+      gchar *language_key;
+  } * lang;
+  sinkpad = (GstPad *) g_list_nth_data(self->sinkpad, 0);
+  GstQuery *cquery;
+  GstStructure *structure;
+  const GValue *value;
+  structure = gst_structure_new ("FileSrcURI", "file-uri", G_TYPE_STRING, NULL, NULL);
+
+  cquery = gst_query_new_application (GST_QUERY_CUSTOM, structure);
+
+  if (!gst_pad_peer_query (sinkpad, cquery)) {
+    GST_ERROR_OBJECT (self, "Failed to query SMI file path");
+    gst_query_unref (cquery);
+    return FALSE;
+  }
+  structure = gst_query_get_structure (cquery);
+  value = gst_structure_get_value (structure, "file-uri");
+  file_path = g_strdup (g_value_get_string (value));
+
+  if (file_path == NULL){
+    GST_ERROR_OBJECT (self, "Could not parse the SMI file path");
+    gst_query_unref (cquery);
+    return FALSE;
+  }
+
+  if (self->external_filepath == NULL) {
+    self->external_filepath = file_path;
+  }
+  else {
+    if (!g_strcmp0 (file_path, self->external_filepath)) {
+      GST_INFO_OBJECT (self, "Same external file URI, no need to parse again");
+      gst_query_unref (cquery);
+      g_free(file_path);
+      return TRUE;
+    }
+    else {
+      g_free (self->external_filepath);
+      self->external_filepath = NULL;
+      self->external_filepath = file_path;
+    }
+  }
+
+  gst_query_unref (cquery);
+  GST_INFO_OBJECT (self, "File path comes as %s", file_path);
+
+  file_path_type = g_strndup ((gchar *) file_path, 4);
+  GST_INFO_OBJECT (self, "Received file path by query = %s, %s", file_path, file_path_type);
+  if (!g_strcmp0(file_path_type, "file")){
+    file_path += 7;
+    GST_INFO_OBJECT (self, "File path comes as %s", file_path);
+
+    fp = fopen (file_path, "r");
+    if (!fp){
+      GST_ERROR_OBJECT (self, "Failed to open file");
+      g_free(file_path_type);
+      return FALSE;
+    }
+
+    for (i = 0; i < list_len; i++){
+      counter[i] = FALSE;
+    }
+
+    while (!feof (fp) && found_count < list_len){
+      GError *err = NULL;
+      gsize * consumed = NULL;
+      gint gap = 0;
+      guint charCount = 0;
+      gchar* result = NULL;
+      gchar* temp = NULL;
+      gchar* temp_lang = NULL;
+      gchar* con_temp_end = NULL;
+      gchar* con_temp_start = NULL;
+      gchar* new_key = NULL;
+      gint new_key_length = 0;
+      gboolean new_key_found = FALSE;
+      gchar * temp1 = NULL;
+      gchar *con_temp_lang = NULL;
+      gchar *con_temp = NULL;
+      gboolean conversion = TRUE;
+      charCount = fread (line, sizeof(char), 1024, fp);
+      line[charCount] = '\0';
+      if (!charCount) {
+        GST_WARNING_OBJECT (self, "fread returned zero bytes");
+        continue;
+      }
+
+      GST_DEBUG_OBJECT (self, "value of detected encoding is %s and self encoding is %s",
+                             self->detected_encoding,self->encoding);
+      if (self->detected_encoding && strcmp (self->detected_encoding, "UTF-8") && conversion){
+        result = convert_to_utf8 (line, charCount, self->detected_encoding, consumed, &err, self);
+      }
+      if (result == NULL) {
+         result = line;
+         conversion =  FALSE;
+      }
+      con_temp = g_utf8_strdown (result, strlen (result));
+      temp = con_temp;
+      while (con_temp) {
+        con_temp = g_strstr_len(con_temp, strlen (con_temp), "class=");
+        if (con_temp) {
+          temp1 = g_strstr_len(con_temp+1, strlen (con_temp), "class=");
+        }
+        if (temp1 && con_temp){
+          gap = strlen (con_temp) - strlen (temp1);
+        } else if (con_temp) {
+          gap = strlen (con_temp);
+        } else {
+          continue;
+        }
+        if (con_temp){
+          for (i = 0; i < list_len; i++){
+            if (counter[i] == TRUE) {
+              con_temp = con_temp + 1;
+              continue;
+            }
+            lang = (struct LangStruct *) g_list_nth_data (lang_list, i);
+            if (lang) {
+              temp_lang = g_strdup(lang->language_key);
+              con_temp_lang = g_utf8_strdown (temp_lang, strlen (temp_lang));
+              if (g_strstr_len (con_temp, gap, con_temp_lang)) {
+                found_count++;
+                counter[i] = TRUE;
+                GST_INFO_OBJECT (self, "Valid Language in list : [%s]", lang->language_key);
+                con_temp = con_temp + 1;
+              }
+/* Fix Me: Cases where there is no body for a specific language
+ * inside a single language .smi file */
+#if 0
+              else {
+                con_temp_start = con_temp;
+                con_temp_end = con_temp;
+                while(con_temp_end) {
+                  if(*con_temp_end == '=') {
+                    con_temp_start = con_temp_end+1;
+                    con_temp_end++;
+                  }else if(*con_temp_end == '>') {
+                    con_temp_end = con_temp_end;
+                    new_key_found = TRUE;
+                    break;
+                  }else {
+                    con_temp_end++;
+                    new_key_found = FALSE;
+                  }
+                }
+                if(new_key_found) {
+                  new_key_length = strlen(con_temp_start)-strlen(con_temp_end);
+                  new_key = g_malloc(new_key_length +1);
+                  for(k=0;k<new_key_length;k++){
+                    *(new_key+k)=*(con_temp_start+k);
+                  }
+                  *(new_key+new_key_length)='\0';
+                  GST_INFO("new lang key is %s",lang->language_key);
+                  g_free(new_key);
+                  found_count++;
+                  counter[i] = TRUE;
+                  con_temp = con_temp + 1;
+                }
+              }
+#endif
+              g_free (temp_lang);
+              g_free (con_temp_lang);
+            }
+          }
+        }
+      }
+      if (conversion)
+        g_free (result);
+      if (temp)
+        g_free (temp);
+    }
+
+    if (found_count < list_len) {
+      for (i = 0; i < list_len; i++) {
+        if (counter[i] == FALSE)
+          lang_list = g_list_delete_link (lang_list, g_list_nth (lang_list, i));
+      }
+    }
+  } else {
+    GST_ERROR_OBJECT (self, "File is not a local file");
+    g_free(file_path_type);
+    return FALSE;
+  }
+  fclose (fp);
+  g_free(file_path_type);
+  return TRUE;
+}
+
+/*
+**
+**  Description    : Chain function used to push the subtitle buffer to internal pipelines of submux element
+**  Params        : (1) sink pad on which buffer is arriving (2) the buffer itself
+**  return        : GST_FLOW_OK on successfully pushing subtitle buffer to next element
+**
+*/
+static GstFlowReturn
+gst_submux_chain(GstPad *pad, GstBuffer *buffer)
+{
+  guint length = 0;
+  guint i=0;
+  GstPad *checkpad = NULL;
+  Gstsubmux *submux = GST_SUBMUX(GST_PAD_PARENT(pad));
+  gboolean ret = FALSE;
+  GstFlowReturn fret = GST_FLOW_ERROR;
+  GstSubmuxStream *stream = NULL;
+  GstMessage *m = NULL;
+
+  if (GST_BUFFER_IS_DISCONT (buffer))
+    GST_DEBUG_OBJECT(submux, "Discont buffer came in chain function");
+  GST_DEBUG_OBJECT (submux, "^^^^^entering in chain^^^^^^");
+  if (!submux->priv->is_internal) {
+    if (!submux->priv->first_buffer) {
+      submux->detected_encoding = detect_encoding ((gchar*)GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
+    }
+    if (!submux->langlist_msg_posted && submux->priv->lang_list) {
+      if (!validate_langlist_body (submux->priv->lang_list, submux)){
+        GST_WARNING_OBJECT(submux, "Error occured while validating language list. Posting without validation");
+      }
+      if (submux->priv->lang_list) {
+        GList* temp_list_to_post = NULL;
+        temp_list_to_post = g_list_copy (submux->priv->lang_list);
+        m = gst_message_new_element (GST_OBJECT_CAST (submux), gst_structure_new("Ext_Sub_Language_List",
+                                    "lang_list", G_TYPE_POINTER, temp_list_to_post, NULL));
+
+        gst_element_post_message (GST_ELEMENT_CAST (submux), m);
+        submux->langlist_msg_posted = TRUE;
+      }
+      GST_DEBUG_OBJECT (submux, "LANGLIST POSTED");
+    }
+    if (submux->need_segment) {
+      ret = gst_pad_push_event (submux->srcpad, gst_event_new_new_segment (FALSE, submux->segment.rate,
+                                submux->segment.format, submux->segment.start, submux->segment.stop,
+                                submux->segment.time));
+      GST_DEBUG_OBJECT (submux, "pushing newsegment event with %" GST_SEGMENT_FORMAT, &submux->segment);
+      if (!ret) {
+        GST_ERROR_OBJECT (submux, "Sending newsegment to next element is failed");
+        return GST_FLOW_ERROR;
+      }
+      GST_DEBUG_OBJECT (submux, "Starting the loop again");
+      if (!gst_pad_start_task (submux->srcpad, (GstTaskFunction) gst_submux_loop, submux)) {
+         GST_ERROR_OBJECT (submux, "failed to start srcpad task...");
+         GST_ELEMENT_ERROR (submux, RESOURCE, FAILED, ("failed to create  push loop"), (NULL));
+         return GST_FLOW_ERROR;
+      }
+      submux->need_segment = FALSE;
+    }
+    GST_DEBUG_OBJECT (submux, "before pushing buffer to each apprsrc");
+    if (!submux->priv->lang_list && submux->priv->parser_type == GST_SUB_PARSE_FORMAT_SAMI) {
+      GST_ERROR_OBJECT (submux, "lang list is not there");
+      return GST_FLOW_ERROR;
+    }
+    if (submux->priv->parser_type == GST_SUB_PARSE_FORMAT_SAMI)
+      length = g_list_length (submux->priv->lang_list);
+    else
+      length = 1;
+
+    for (i = 0; i < length; i++) {
+      stream = g_list_nth_data(submux->streams, i);
+      if ((submux->priv->parser_type == GST_SUB_PARSE_FORMAT_SAMI) && !submux->priv->first_buffer){
+        GstLangStruct *lang = g_list_nth_data(submux->priv->lang_list, i);
+        if(submux->msl_streams){
+           GstLangStruct *lang1 = g_list_nth_data(submux->msl_streams, i);
+           lang->active = lang1->active;
+        } else {
+          if (i == 0)
+            lang->active = TRUE;
+          else
+            lang->active = FALSE;
+        }
+      }
+      GST_DEBUG_OBJECT (submux, "making stream need segment false");
+      stream->need_segment = FALSE;
+    }
+
+    for (i = 0; i < length; i++) {
+      stream = g_list_nth_data(submux->streams, i);
+      if (!stream){
+        GST_ERROR_OBJECT (submux, "stream not found");
+        return GST_FLOW_ERROR;
+      }
+
+      if (!stream->pipe_struc.appsrc) {
+        GST_ERROR_OBJECT (submux, "appsrc not found");
+        return GST_FLOW_ERROR;
+      }
+      if (i < (length - 1))
+        gst_buffer_ref (buffer);
+
+      fret = gst_app_src_push_buffer ((GstAppSrc*)stream->pipe_struc.appsrc, buffer);
+
+      if (fret != GST_FLOW_OK) {
+        GST_ERROR_OBJECT (submux, "push buffer failed with fret is %d", fret);
+        return fret;
+      }
+      GST_DEBUG_OBJECT (submux, "pad_push successfull to appsrc %p buffer", buffer);
+    }
+  } else {
+    length = submux->sinkpads_count;
+    checkpad = (GstPad *) g_list_nth_data (submux->sinkpad, 0);
+    if (checkpad == pad) {
+      if (submux->need_segment) {
+        ret = gst_pad_push_event (submux->srcpad, gst_event_new_new_segment (FALSE, submux->segment.rate,
+                                  submux->segment.format, submux->segment.start, submux->segment.stop,
+                                  submux->segment.time));
+        GST_DEBUG_OBJECT (submux, "pushing newsegment event with %" GST_SEGMENT_FORMAT, &submux->segment);
+        if (!ret) {
+          GST_ERROR_OBJECT (submux, "Sending newsegment to next element is failed");
+          return GST_FLOW_ERROR;
+        }
+        GST_DEBUG_OBJECT (submux, "Starting the loop again");
+        if (!gst_pad_start_task (submux->srcpad, (GstTaskFunction) gst_submux_loop, submux)) {
+          GST_ERROR_OBJECT (submux, "failed to start srcpad task...");
+          GST_ELEMENT_ERROR (submux, RESOURCE, FAILED, ("failed to create  push loop"), (NULL));
+          return GST_FLOW_ERROR;
+        }
+        submux->need_segment = FALSE;
+      }
+    }
+    for (i = 0; i < length; i++) {
+      checkpad = (GstPad *) g_list_nth_data(submux->sinkpad, i);
+      if (checkpad == pad) {
+        stream = g_list_nth_data (submux->streams, i);
+        if (!stream) {
+          GST_ERROR_OBJECT (submux, "Stream not available...");
+          return GST_FLOW_ERROR;
+        }
+        if (stream->flushing){
+          GST_DEBUG_OBJECT (submux, "flushing going on in appsink");
+          return GST_FLOW_OK ;
+        }
+
+        g_mutex_lock (stream->queue_lock);
+        g_queue_push_tail (stream->queue, buffer);
+        g_cond_signal (stream->queue_empty);
+        g_mutex_unlock (stream->queue_lock);
+        fret = GST_FLOW_OK;
+        GST_DEBUG_OBJECT (submux, "push buffer success to appsrc with fret is %d for stream[%d]", fret, i);
+        break;
+      }
+    }
+  }
+
+  if (!submux->priv->first_buffer) {
+    GST_DEBUG_OBJECT (submux, "got the first buffer");
+    submux->priv->first_buffer = TRUE;
+    if (submux->priv->parser_type == GST_SUB_PARSE_FORMAT_SAMI) {
+
+    }
+  }
+  GST_DEBUG_OBJECT (submux, "^^^^^exiting in chain^^^^^^");
+  return fret;
+}
+
+/* stream_denit */
+static void
+gst_submux_stream_deinit (GstSubmuxStream *stream,Gstsubmux *submux)
+{
+  GstBuffer *buf = NULL;
+
+  if (stream) {
+    if (stream->queue) {
+      while (!g_queue_is_empty (stream->queue)) {
+        buf = g_queue_pop_head (stream->queue);
+        gst_buffer_unref (buf);
+        buf = NULL;
+      }
+      g_queue_free (stream->queue);
+      stream->queue = NULL;
+    }
+
+    if (stream->pipe_struc.pipe) {
+      gst_element_set_state (stream->pipe_struc.pipe, GST_STATE_NULL);
+      gst_element_get_state (stream->pipe_struc.pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+      gst_object_unref(GST_OBJECT(stream->pipe_struc.appsrc));
+      gst_object_unref(GST_OBJECT(stream->pipe_struc.appsink));
+      gst_object_unref (stream->pipe_struc.pipe);
+    }
+
+    if (stream->queue_lock) {
+      g_cond_broadcast(stream->queue_empty);
+      g_mutex_free (stream->queue_lock);
+      stream->queue_lock = NULL;
+    }
+
+    if (stream->queue_empty) {
+      g_cond_free (stream->queue_empty);
+      stream->queue_empty= NULL;
+    }
+
+    g_free (stream);
+    GST_DEBUG_OBJECT (submux, "stream deinit completed");
+  }
+}
+
+/* releasing the requested pad */
+static void
+gst_submux_release_pad (GstElement * element, GstPad * pad)
+{
+  Gstsubmux *submux = GST_SUBMUX_CAST (element);
+  GstPad *check_pad;
+  int i=0;
+  guint length;
+  GST_INFO_OBJECT(element,"entering in the release pad");
+  length = g_list_length(submux->sinkpad);
+  GST_DEBUG_OBJECT (element, "Releasing %s:%s", GST_DEBUG_PAD_NAME (pad));
+
+  for (i=1;i<=length;i++) {
+         check_pad = (struct GstPad *) g_list_nth_data(submux->sinkpad,i);
+    if (check_pad == pad) {
+      /* this is it, remove */
+      submux->sinkpad = g_list_remove_link (submux->sinkpad, pad);
+      gst_element_remove_pad (element, pad);
+      break;
+    }
+  }
+}
+
+/* request new pad */
+static GstPad *
+gst_submux_request_new_pad (GstElement * element,
+    GstPadTemplate * templ, const gchar * req_name)
+{
+  GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
+  Gstsubmux *submux = GST_SUBMUX_CAST (element);
+  GstPad *newpad = NULL;
+  gchar *name = NULL;
+
+  if (templ->direction != GST_PAD_SINK) {
+    GST_ERROR_OBJECT (submux, "templ direction is not sinkpad, returning from here");
+    goto wrong_direction;
+  }
+
+  if (templ == gst_element_class_get_pad_template (klass, "sink%d")) {
+    name = g_strdup_printf ("sink%d", submux->sinkpads_count++);
+  }
+
+  GST_DEBUG_OBJECT (submux, "Requested pad: %s", name);
+  newpad = (GstPad*)g_new0 (GstPad*, 1);
+  /* create pad and add to collections */
+  newpad = gst_pad_new_from_template (templ, name);
+  g_free (name);
+  if(!submux->priv->is_internal) {
+    submux->external_sinkpad = TRUE;
+  }
+  submux->sinkpad = g_list_append (submux->sinkpad, newpad);
+  /* set up pad */
+
+  /* set up pad functions */
+  gst_pad_set_setcaps_function (newpad, GST_DEBUG_FUNCPTR (gst_submux_setcaps));
+  gst_pad_set_event_function (newpad, GST_DEBUG_FUNCPTR (gst_submux_handle_sink_event));
+  gst_pad_set_chain_function(newpad, GST_DEBUG_FUNCPTR (gst_submux_chain));
+  gst_pad_set_active (newpad, TRUE);
+  gst_element_add_pad (element, newpad);
+
+  return newpad;
+
+/* ERRORS */
+wrong_direction:
+  GST_WARNING_OBJECT (submux, "Request pad that is not a SINK pad.");
+  return NULL;
+}
+
+static gboolean
+gst_submux_handle_src_event (GstPad * pad, GstEvent * event)
+{
+  Gstsubmux *submux = GST_SUBMUX(GST_PAD_PARENT(pad));
+  gboolean ret = FALSE;
+  guint length = 0;
+  gint i = 0;
+  gboolean update;
+  GstSubmuxStream *cur_stream = NULL;
+
+  GST_DEBUG_OBJECT (submux, "Handling %s event", GST_EVENT_TYPE_NAME (event));
+  length = g_list_length(submux->streams);
+
+  switch (GST_EVENT_TYPE (event)) {
+    /* this event indicates speed change or seek */
+    case GST_EVENT_SEEK: {
+      GstFormat format;
+      GstSeekType start_type, stop_type;
+      gint64 start, stop;
+      gdouble rate;
+      GstPad *sinkpad = (GstPad *) g_list_nth_data (submux->sinkpad, 0);
+      gst_event_parse_seek (event, &rate, &format, &submux->segment_flags,
+                             &start_type, &start, &stop_type, &stop);
+      gst_segment_set_seek (&submux->segment, rate, format, submux->segment_flags,
+                             start_type, start, stop_type, stop, &update);
+      if (submux->priv->is_internal || submux->priv->parser_type != GST_SUB_PARSE_FORMAT_SAMI) {
+        length = g_list_length (submux->sinkpad);
+      } else {
+        length = g_list_length(submux->streams);
+      }
+      if (!submux->priv->is_internal) {
+        ret = gst_pad_push_event (sinkpad, gst_event_new_seek (rate, GST_FORMAT_BYTES, submux->segment_flags,
+                                  GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, 0));
+        gst_event_unref (event);
+      } else {
+        GST_DEBUG_OBJECT (submux, "handling seek in case of internal");
+        ret = gst_pad_event_default (pad, event);
+      }
+
+      if (!ret) {
+        GST_ERROR_OBJECT (submux, "sending seek event to sink pad failed");
+        break;
+      }
+      GST_DEBUG_OBJECT (submux, "sending seek event to sink pad passed");
+
+      break;
+    }
+
+    default: {
+      ret = gst_pad_event_default (pad, event);
+      break;
+    }
+  }
+
+  return ret;
+}
+
+static gboolean
+gst_submux_handle_sink_event (GstPad * pad, GstEvent * event)
+{
+  Gstsubmux *submux = GST_SUBMUX (GST_PAD_PARENT (pad));
+  gboolean ret = FALSE;
+  guint length = 0;
+  GstBuffer *buf = NULL;
+  GstPad *checkpad = NULL;
+  gint i = 0;
+  GstSubmuxStream *cur_stream = NULL;
+
+  GST_DEBUG_OBJECT (submux, "Handling %s event", GST_EVENT_TYPE_NAME (event));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_EOS:{
+      length = g_list_length (submux->sinkpad);
+      GST_OBJECT_LOCK (submux);
+      for (i = 0; i < length; i++) {
+        GST_DEBUG_OBJECT(submux, "inside the handling of EOS event");
+        cur_stream = g_list_nth_data(submux->streams,i);
+        if (!cur_stream->eos_sent) {
+          GstBuffer *buf = gst_buffer_new_and_alloc (3 + 1);
+          GST_DEBUG_OBJECT(submux, "sending EOS buffer to chain\n");
+          GST_DEBUG_OBJECT (submux, "EOS. Pushing remaining text (if any)");
+          GST_BUFFER_DATA (buf)[0] = 'e';
+          GST_BUFFER_DATA (buf)[1] = 'o';
+          GST_BUFFER_DATA (buf)[2] = 's';
+          GST_BUFFER_DATA (buf)[3] = '\0';
+          /* play it safe */
+          GST_BUFFER_SIZE (buf) = 3;
+          GST_BUFFER_FLAG_SET(buf,GST_BUFFER_FLAG_GAP);
+          gst_submux_chain (g_list_nth_data(submux->sinkpad,i), buf);//
+          cur_stream->eos_sent = TRUE;
+        }
+      }
+      GST_OBJECT_UNLOCK (submux);
+      gst_event_unref(event);
+      ret = TRUE;
+      break;
+    }
+    case GST_EVENT_NEWSEGMENT: {
+      GstFormat format;
+      gdouble rate,arate;
+      gint64 start, stop, time;
+      gboolean update;
+      GST_OBJECT_LOCK (submux);
+      if (!submux->pipeline_made) {
+        if (!gst_submux_format_autodetect (submux)) {
+          GST_ERROR_OBJECT (submux, "auto detect function failed");
+          return FALSE;
+        }
+        if (!gst_calculate_number_languages(submux)) {
+          GST_ERROR_OBJECT (submux, "failed to calculate number of languages");
+          return FALSE;
+        }
+        if (!gst_submux_create_pipelines (submux, pad)) {
+          GST_ERROR_OBJECT (submux, "failed to create pipelines");
+          return FALSE;
+        }
+     }
+
+      if (!submux->priv->is_internal) {
+        gst_event_unref(event);
+        length = g_list_length(submux->streams);
+        for (i = 0; i < length; i++) {
+          GST_DEBUG_OBJECT (submux, "inside the handling of new_segment event");
+          cur_stream = g_list_nth_data(submux->streams,i);
+          GST_DEBUG_OBJECT (submux, "pushing newsegment event with %" GST_SEGMENT_FORMAT, &submux->segment);
+          if (!cur_stream->pipe_struc.pipe) {
+            GST_ERROR_OBJECT (submux, "pipeline is null");
+            return FALSE;
+          }
+          cur_stream = g_list_nth_data(submux->streams,i);
+          cur_stream->seek_ts = submux->segment.start;
+          ret = gst_element_send_event (cur_stream->pipe_struc.pipe, gst_event_new_new_segment (FALSE,
+                                        submux->segment.rate, submux->segment.format,
+                                        submux->segment.start, submux->segment.stop, submux->segment.time));
+          if (!ret){
+            GST_ERROR_OBJECT(submux, "sending newsegment event to stream[%d] failed", i);
+            break;
+          }
+        }
+        submux->need_segment = TRUE;
+      } else {
+        length = g_list_length (submux->sinkpad);
+        if (length ==  g_list_length (submux->streams) && submux->need_segment) {
+          for (i = 0; i < length; i++) {
+            GST_DEBUG_OBJECT (submux, "inside the handling of new_segment event");
+            cur_stream = g_list_nth_data(submux->streams, i);
+            if (cur_stream->need_segment) {
+              gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, &start, &stop, &time);
+              gst_segment_set_newsegment_full (&submux->segment, update, rate, arate, format, start, stop, time);
+              GST_DEBUG_OBJECT (submux, "pushing newsegment event with %" GST_SEGMENT_FORMAT, &submux->segment);
+              ret = TRUE;
+              cur_stream->need_segment = FALSE;
+            }
+          }
+          submux->need_segment = TRUE;
+          gst_event_unref(event);
+        }
+      }
+      GST_OBJECT_UNLOCK (submux);
+      break;
+    }
+    case GST_EVENT_FLUSH_START: {
+      length = g_list_length(submux->streams);
+      if (!submux->priv->is_internal) {
+        gst_event_unref(event);
+        ret = gst_pad_event_default (pad, gst_event_new_flush_start ());
+        for (i = 0;i < length;i++) {
+          cur_stream = g_list_nth_data(submux->streams,i);
+          cur_stream->flushing = TRUE;
+          cur_stream->discont_came = FALSE;
+          GST_DEBUG_OBJECT (submux, "making discont false");
+          GST_DEBUG_OBJECT (submux, "making flushing TRUE");
+          cur_stream->eos_came = FALSE;
+          cur_stream->eos_sent = FALSE;
+          GST_DEBUG_OBJECT (submux, "making eos_came and eos_sent FALSE");
+        }
+        for (i = 0; i < length; i++) {
+          cur_stream = g_list_nth_data(submux->streams,i);
+          ret= gst_element_send_event(cur_stream->pipe_struc.appsrc,gst_event_new_flush_start ());
+          ret= gst_element_send_event(cur_stream->pipe_struc.appsrc,gst_event_new_flush_stop ());
+          ret = gst_element_send_event(cur_stream->pipe_struc.appsrc,gst_event_new_eos ());
+          GST_INFO_OBJECT(cur_stream,"flush stop and start  and eos is done with ret %d",ret);
+          submux->flushing =TRUE;
+          g_mutex_lock (cur_stream->queue_lock);
+          g_cond_signal (cur_stream->queue_empty);
+          g_mutex_unlock(cur_stream->queue_lock);
+          cur_stream->flush_done = TRUE;
+          GST_DEBUG_OBJECT (cur_stream, "signaling queue empty signal from flush start");
+          ret = TRUE;
+          GST_DEBUG_OBJECT (submux, "sending flush start event to stream[%d] success", i);
+        }
+
+        if (!ret){
+          GST_ERROR_OBJECT (submux, "sending flush start event to srcpad pad failed");
+          break;
+        }
+
+        if (submux && GST_PAD_TASK(submux->srcpad)) {
+          GST_INFO_OBJECT (submux, "trying acquire srcpad lock");
+          GST_PAD_STREAM_LOCK (submux->srcpad);
+          GST_INFO_OBJECT (submux, "acquired stream lock");
+          GST_PAD_STREAM_UNLOCK (submux->srcpad);
+        }
+        /*changes for new design*/
+        for (i = 0;i < length;i++) {
+          cur_stream = g_list_nth_data(submux->streams,i);
+          gst_submux_stream_deinit(cur_stream,submux);
+        }
+        g_list_free(submux->streams);
+        submux->streams = NULL;
+        gst_submux_deinit_private_values (submux);
+
+        submux->stop_loop = FALSE;
+        submux->need_segment = TRUE;
+        submux->langlist_msg_posted = FALSE;
+        GST_DEBUG_OBJECT (submux, "flush start successfully send to next element");
+      } else {
+        GST_DEBUG_OBJECT(submux, "flusht start in case of internal subtitle");
+        gst_event_unref (event);
+        submux->flushing = TRUE;
+        checkpad = (GstPad *) g_list_nth_data (submux->sinkpad, length - 1);
+        if (checkpad == pad) {
+          ret = gst_pad_event_default (pad, gst_event_new_flush_start ());
+          for (i = 0; i < length; i++) {
+            cur_stream = g_list_nth_data(submux->streams, i);
+            cur_stream->flushing = TRUE;
+            GST_DEBUG_OBJECT (submux, "in case of internal making discont unchanged");
+            GST_DEBUG_OBJECT (submux, "making flushing TRUE");
+          }
+          for (i = 0; i < length; i++) {
+            cur_stream = g_list_nth_data(submux->streams, i);
+            submux->flushing = TRUE;
+            g_mutex_lock (cur_stream->queue_lock);
+            while (!g_queue_is_empty (cur_stream->queue)) {
+              buf = g_queue_pop_head (cur_stream->queue);
+              gst_buffer_unref (buf);
+            }
+            GST_DEBUG_OBJECT (submux, "cleared stream cur_stream->queue");
+            g_queue_clear (cur_stream->queue);
+            g_cond_signal (cur_stream->queue_empty);
+            g_mutex_unlock(cur_stream->queue_lock);
+            GST_DEBUG_OBJECT (cur_stream, "signaling queue empty signal from flush start");
+            cur_stream->eos_came = FALSE;
+            cur_stream->eos_sent = FALSE;
+            GST_DEBUG_OBJECT (submux, "making eos_came and eos_sent FALSE");
+            ret = TRUE;
+            GST_DEBUG_OBJECT (submux, "sending flush start event to stream[%d] success", i);
+          }
+          if (!ret){
+            GST_ERROR_OBJECT (submux, "sending flush start event to srcpad pad failed");
+            break;
+          }
+
+          if (submux && GST_PAD_TASK (submux->srcpad)) {
+            GST_INFO_OBJECT (submux, "trying acquire srcpad lock");
+            GST_PAD_STREAM_LOCK (submux->srcpad);
+            GST_INFO_OBJECT (submux, "acquired srcpad lock");
+            GST_PAD_STREAM_UNLOCK (submux->srcpad);
+          }
+          GST_DEBUG_OBJECT(submux, "flush start successfully send to next element");
+         }
+      }
+      break;
+    }
+    case GST_EVENT_FLUSH_STOP: {
+      gst_event_unref(event);
+      if (!submux->priv->is_internal) {
+        guint idx = 0;
+        submux->flushing = FALSE;
+        ret = gst_pad_event_default (pad, gst_event_new_flush_stop ());
+        if (!ret){
+          GST_ERROR_OBJECT (submux, "sending flush-stop event to srcpad pad failed");
+          break;
+        }
+        for (idx = 0; idx < submux->priv->stream_count; idx++) {
+          submux->cur_buf_array[idx] = NULL;
+        }
+        GST_DEBUG_OBJECT (submux, "flush stop successfully send to next element");
+      } else {
+        length = g_list_length(submux->streams);
+        GST_DEBUG_OBJECT (submux, "flusht stop in case of internal subtitle");
+        checkpad = (GstPad *) g_list_nth_data (submux->sinkpad, length - 1);
+        if (checkpad == pad) {
+          for (i = 0; i < length; i++) {
+            cur_stream = g_list_nth_data(submux->streams, i);
+            cur_stream->need_segment = TRUE;
+            submux->cur_buf_array[i] = NULL;
+            submux->need_segment = TRUE;
+            GST_DEBUG_OBJECT (submux, "making need_segment true");
+            submux->flushing = FALSE;
+            cur_stream->flushing = FALSE;
+            GST_DEBUG_OBJECT (submux, "making flushing FALSE");
+            ret = TRUE;
+            GST_DEBUG_OBJECT (submux, "sending %s event to stream[%d] success", GST_EVENT_TYPE_NAME (event), i);
+          }
+          ret = gst_pad_event_default (pad, gst_event_new_flush_stop ());
+          if (!ret){
+            GST_ERROR_OBJECT (submux, "sending flush-stop event to srcpad pad failed");
+            break;
+          }
+          GST_DEBUG_OBJECT (submux, "flush stop successfully send to next element");
+        }
+      }
+      break;
+    }
+    default:{
+      if (!submux->priv->is_internal) {
+        ret = gst_pad_event_default (pad, event);
+      } else {
+        checkpad = (GstPad *) g_list_nth_data (submux->sinkpad, length - 1);
+        if (checkpad == pad) {
+          ret = gst_pad_event_default (pad, event);
+        } else {
+          ret = TRUE;
+        }
+      }
+      if (!ret){
+        GST_ERROR_OBJECT (submux, "sending %s event to srcpad pad failed", GST_EVENT_TYPE_NAME (event));
+        break;
+      }
+      break;
+    }
+  }
+  return ret;
+}
+
+static gint gst_submux_buffer_list_sorting (gconstpointer a, gconstpointer b)
+{
+  GstBuffer *buf_a = (GstBuffer *) a;
+  GstBuffer *buf_b = (GstBuffer *) b;
+  if (GST_BUFFER_TIMESTAMP(buf_a)>GST_BUFFER_TIMESTAMP(buf_b))
+    return -1;
+  else if(GST_BUFFER_TIMESTAMP(buf_a)<GST_BUFFER_TIMESTAMP(buf_b))
+    return 1;
+  else
+    return 0;
+}
+
+static gboolean
+gst_submux_is_muxing_needed (GstBuffer *ref_buffer, GstBuffer *cur_buf)
+{
+  GstClockTime ref_start = GST_BUFFER_TIMESTAMP(ref_buffer);
+  GstClockTime ref_stop = GST_BUFFER_TIMESTAMP(ref_buffer) + GST_BUFFER_DURATION(ref_buffer);
+  GstClockTime start = GST_BUFFER_TIMESTAMP(cur_buf);
+  GstClockTime stop = GST_BUFFER_TIMESTAMP(cur_buf) + GST_BUFFER_DURATION(cur_buf);
+
+  /* if we have a stop position and a valid start and start is bigger,
+   * we're outside of the segment */
+  if (G_UNLIKELY (ref_stop != -1 && start != -1 && start >= ref_stop))
+    return FALSE;
+
+  /* if a stop position is given and is before the segment start,
+   * we're outside of the segment. Special case is were start
+   * and stop are equal to the segment start. In that case we
+   * are inside the segment. */
+  if (G_UNLIKELY (stop != -1 && (stop < ref_start || (start != stop && stop == ref_start))))
+    return FALSE;
+
+  return TRUE;
+}
+
+/* This function do the actual muxing of buffer on the basis of timestamps */
+static GList*
+gst_submux_muxing (Gstsubmux *submux)
+{
+  GstClockTime min_timestamp = 0;
+  int min_stream = 0;
+  int overlap = 0;
+  GstClockTime next_min_time = 0;
+  int idx = 0;
+  GList *push_list = NULL;
+
+  /* Finding least timestamp of all streams and their stream ID */
+  for (idx = 0; idx < submux->priv->stream_count; idx++) {
+    if(submux->cur_buf_array[idx] && !min_timestamp) {
+      min_timestamp = GST_BUFFER_TIMESTAMP(submux->cur_buf_array[idx]);
+      min_stream = idx;
+    }
+    if(submux->cur_buf_array[idx] && (GST_BUFFER_TIMESTAMP(submux->cur_buf_array[idx]) < min_timestamp)) {
+      min_timestamp = GST_BUFFER_TIMESTAMP(submux->cur_buf_array[idx]);
+      min_stream = idx;
+    }
+  }
+
+  GST_DEBUG_OBJECT (submux, "Identified least timestamp: %"GST_TIME_FORMAT" for stream: %d",
+    GST_TIME_ARGS(min_timestamp), min_stream);
+
+  /* Finding overlap buffers and next least timestamp */
+  for (idx = 0; idx < submux->priv->stream_count; idx++) {
+    if(submux->cur_buf_array[idx] && (idx != min_stream) && (!next_min_time)) {
+      next_min_time = GST_BUFFER_TIMESTAMP(submux->cur_buf_array[idx]);
+    }
+    if(submux->cur_buf_array[idx] && (idx != min_stream)) {
+      if(gst_submux_is_muxing_needed (submux->cur_buf_array[min_stream], submux->cur_buf_array[idx])) {
+        overlap = overlap | (1<<idx);      // bit setting of overlap variable with stream ID
+        GST_DEBUG_OBJECT (submux, "overlapped with stream = %d", idx);
+        if(GST_BUFFER_TIMESTAMP(submux->cur_buf_array[idx]) < next_min_time)
+          next_min_time = GST_BUFFER_TIMESTAMP(submux->cur_buf_array[idx]);
+      }
+    }
+  }
+
+  GST_DEBUG_OBJECT (submux, "Identified overlap: %d next least timestamp: %"GST_TIME_FORMAT" ", overlap, GST_TIME_ARGS(next_min_time));
+
+  /* If no overlap send buffer as it is */
+  if(!overlap) {
+     GST_DEBUG_OBJECT (submux, "pushing string: %s....", (gchar*)GST_BUFFER_DATA(submux->cur_buf_array[min_stream]));
+     push_list = g_list_append(push_list, submux->cur_buf_array[min_stream]);
+     GST_DEBUG_OBJECT (submux, "No overlap found pushing buffer of ts = %"GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT,
+              GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(submux->cur_buf_array[min_stream])), GST_TIME_ARGS(GST_BUFFER_DURATION(submux->cur_buf_array[min_stream])));
+     submux->cur_buf_array[min_stream] = NULL;
+  } else {
+    GstBuffer *push_buf = NULL;
+    GstClockTime stop_time = 0;
+    int stop_idx = 0;
+    GstBuffer *overlap_buf = NULL;
+    guint overlap_buf_length = 0;
+    GString *overlap_text = NULL;
+    gchar *text = NULL;
+
+    if(next_min_time > GST_BUFFER_TIMESTAMP(submux->cur_buf_array[min_stream])) {
+    GST_DEBUG_OBJECT (submux, "Before duration change ts = %"GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT,
+             GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(submux->cur_buf_array[min_stream])), GST_TIME_ARGS(GST_BUFFER_DURATION(submux->cur_buf_array[min_stream])));
+      push_buf = gst_buffer_copy (submux->cur_buf_array[min_stream]);
+      push_buf->duration = next_min_time - GST_BUFFER_TIMESTAMP(submux->cur_buf_array[min_stream]);
+      GST_BUFFER_TIMESTAMP(submux->cur_buf_array[min_stream]) = next_min_time;
+      GST_BUFFER_DURATION(submux->cur_buf_array[min_stream]) -= push_buf->duration;
+      GST_DEBUG_OBJECT (submux, "After duration change ts = %"GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT,
+             GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(submux->cur_buf_array[min_stream])), GST_TIME_ARGS(GST_BUFFER_DURATION(submux->cur_buf_array[min_stream])));
+
+      min_timestamp = next_min_time;
+      GST_INFO_OBJECT (submux, "pushing string: %s...", (gchar*)GST_BUFFER_DATA(push_buf));
+      push_list = g_list_append(push_list, push_buf);
+      GST_DEBUG_OBJECT (submux, "Overlap found pushing initial partial buffer of ts = %"GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT,
+              GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(push_buf)), GST_TIME_ARGS(GST_BUFFER_DURATION(push_buf)));
+    }
+
+    for (idx = 0; idx < submux->priv->stream_count; idx++) {
+      if(submux->cur_buf_array[idx] && !stop_time) {
+        stop_time = GST_BUFFER_TIMESTAMP(submux->cur_buf_array[idx]) + GST_BUFFER_DURATION(submux->cur_buf_array[idx]);
+        stop_idx = idx;
+      }
+      if(submux->cur_buf_array[idx] &&
+          ((GST_BUFFER_TIMESTAMP(submux->cur_buf_array[idx])+ GST_BUFFER_DURATION(submux->cur_buf_array[idx])) < stop_time)) {
+        stop_time = GST_BUFFER_TIMESTAMP(submux->cur_buf_array[idx]) + GST_BUFFER_DURATION(submux->cur_buf_array[idx]);
+        stop_idx = idx;
+      }
+    }
+    GST_DEBUG_OBJECT (submux, "Identified least stop timestamp: %"GST_TIME_FORMAT" for stream: %d",
+            GST_TIME_ARGS(stop_time), stop_idx);
+
+    overlap_text = g_string_new ("");
+    overlap = overlap | (1<<min_stream);
+    for (idx = 0; idx < submux->priv->stream_count; idx++) {
+      int finder = 1<<idx;
+      if(overlap & finder) {
+        GST_DEBUG_OBJECT (submux, "append string: %s....", (gchar*)GST_BUFFER_DATA(submux->cur_buf_array[idx]));
+        g_string_append (overlap_text, (gchar*)GST_BUFFER_DATA (submux->cur_buf_array[idx]));
+        GST_BUFFER_TIMESTAMP(submux->cur_buf_array[idx])+= (stop_time - min_timestamp);
+        GST_BUFFER_DURATION(submux->cur_buf_array[idx])-= (stop_time - min_timestamp);
+        if(overlap > (1<<(idx+1))) g_string_append_c (overlap_text, '\n');
+      }
+    }
+    text = g_string_free (overlap_text, FALSE);
+    overlap_buf_length = strlen(text);
+    overlap_buf = gst_buffer_new_and_alloc (overlap_buf_length + 1);
+    memcpy (GST_BUFFER_DATA (overlap_buf), text, overlap_buf_length + 1);
+    overlap_buf->timestamp = min_timestamp;
+    overlap_buf->duration = stop_time - min_timestamp;
+    g_free (text);
+    text = NULL;
+    submux->cur_buf_array[stop_idx] = NULL;
+    GST_DEBUG_OBJECT (submux, "pushing string: %s....", (gchar*)GST_BUFFER_DATA(overlap_buf));
+    push_list = g_list_append(push_list, overlap_buf);
+    GST_DEBUG_OBJECT (submux, "Overlap found pushing merged buffer of ts = %"GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT,
+          GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(overlap_buf)), GST_TIME_ARGS(GST_BUFFER_DURATION(overlap_buf)));
+    GST_DEBUG_OBJECT (submux, "request for new buffer for stream %d", stop_idx);
+    for (idx = 0; idx < submux->priv->stream_count; idx++) {
+      if(submux->cur_buf_array[idx] &&
+           ((GST_BUFFER_TIMESTAMP(submux->cur_buf_array[idx])+ GST_BUFFER_DURATION(submux->cur_buf_array[idx])) <= stop_time)) {
+        submux->cur_buf_array[idx] = NULL;
+        GST_DEBUG_OBJECT (submux, "request for new buffer for stream %d", idx);
+      }
+    }
+  }
+  return push_list;
+}
+
+static void gst_submux_loop (Gstsubmux *submux)
+{
+  guint length = 0;
+  GstBuffer *src_buffer = NULL;
+  GstBuffer *temp_buffer = NULL;
+  GstBuffer *check_buffer = NULL;
+  GstSubmuxStream *cur_stream = NULL;
+  GstSubmuxStream *check_stream = NULL;
+  gboolean match = FALSE;
+  GstFlowReturn fret = GST_FLOW_OK;
+  GstClockTime cur_duration = 0 ;
+  GstClockTime cur_ts = 0;
+  gboolean eos = TRUE;
+  guint i= 0,k = 0;
+  GList *push_list = NULL;
+  GstBuffer *push_buf = NULL;
+
+  if (!submux->priv->first_buffer) {
+    GST_INFO_OBJECT (submux, "exiting from lopp");
+    return;
+  }
+
+  if (submux->priv->parser_type == GST_SUB_PARSE_FORMAT_SAMI) {
+    length = g_list_length (submux->priv->lang_list);
+  } else {
+    length = submux->sinkpads_count;
+  }
+
+  gboolean made = FALSE;
+ // length = 2;
+
+  for (i = 0; i < length; i++) {
+
+re_pop:
+    cur_stream = g_list_nth_data (submux->streams, i);
+    GST_DEBUG_OBJECT (submux, "Before lock acquired in loop stream[%d]", i);
+    g_mutex_lock (cur_stream->queue_lock);
+    GST_DEBUG_OBJECT (submux, "Lock acquired in loop stream[%d]", i);
+
+    if (g_queue_is_empty (cur_stream->queue) && !submux->flushing) {
+      GST_DEBUG_OBJECT (submux, "Queue is empty, waiting for the condition signal stream[%d]", i);
+      g_cond_wait (cur_stream->queue_empty, cur_stream->queue_lock);
+    }
+    GST_DEBUG_OBJECT (submux, "Got the queue condition signal stream[%d]", i);
+
+    if (submux->flushing || submux->stop_loop) {
+      GST_DEBUG_OBJECT (submux, "Flushing going on in loop");
+      GST_DEBUG_OBJECT (submux, "Got the condition signal");
+      g_mutex_unlock (cur_stream->queue_lock);
+      goto error;
+    }
+
+    check_buffer = g_queue_peek_head (cur_stream->queue);
+    if (!strcmp ((const char*)GST_BUFFER_DATA (check_buffer), "eos")){
+      cur_stream->eos_came = TRUE;
+      GST_DEBUG_OBJECT (submux, "Eos recieved for stream");
+    }
+    for (k = 0; k < length; k++)  {
+      check_stream = g_list_nth_data(submux->streams, k);
+      if (!check_stream->eos_came) {
+        eos = FALSE;
+        break;
+      } else {
+        eos = TRUE;
+      }
+    }
+    if (eos) {
+      GST_DEBUG_OBJECT (submux, "Sending EOS to submux srcpad");
+      gst_pad_push_event(submux->srcpad, gst_event_new_eos ());
+      g_mutex_unlock (cur_stream->queue_lock);
+      goto eos_sent;
+    }
+
+    if (!cur_stream->eos_came && (submux->priv->parser_type == GST_SUB_PARSE_FORMAT_SAMI ||
+                                  submux->priv->is_internal)) {
+      GstLangStruct *lang = NULL;
+      if (submux->priv->lang_list) {
+        if (submux->cur_buf_array[i] == NULL) {
+          check_buffer = g_queue_pop_head (cur_stream->queue);
+          lang = g_list_nth_data(submux->priv->lang_list, i);
+          if (!lang->active) {
+            if(check_buffer) {
+              gst_buffer_unref(check_buffer);
+              check_buffer = NULL;
+              GST_DEBUG_OBJECT (submux, "unreffing the non-active stream[%d] buffer", i);
+            }
+            submux->cur_buf_array[i] = NULL;
+            g_mutex_unlock (cur_stream->queue_lock);
+            GST_DEBUG_OBJECT(submux,"rejecting not selected language");
+            continue;
+          } else {
+            if (!check_buffer) {
+              GST_WARNING_OBJECT (submux, "checkbuffer null.. repop");
+              g_mutex_unlock (cur_stream->queue_lock);
+              goto re_pop;
+            }
+            if (!GST_BUFFER_DURATION(check_buffer)) {
+              GST_WARNING_OBJECT (submux, "duration of buffer is zero..re-pop");
+              gst_buffer_unref (check_buffer);
+              g_mutex_unlock (cur_stream->queue_lock);
+              goto re_pop;
+            }
+            submux->cur_buf_array[i] = check_buffer;
+            GST_DEBUG_OBJECT (submux, "consuming active stream [%d] buffer : ts = %"GST_TIME_FORMAT"and dur = %"GST_TIME_FORMAT,
+              i, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (check_buffer)), GST_TIME_ARGS(GST_BUFFER_DURATION (check_buffer)));
+          }
+        }
+      } else {
+        g_mutex_unlock (cur_stream->queue_lock);
+        GST_DEBUG_OBJECT(submux,"Coming to Else case lang submux->priv->lang_list %x ",submux->priv->lang_list);
+        continue;
+      }
+    } else if (!cur_stream->eos_came) {
+      /* External subtitle format other than smi */
+      if (submux->sinkpad) {
+        if (submux->cur_buf_array[i] == NULL) {
+          check_buffer = g_queue_pop_head (cur_stream->queue);
+          if (!check_buffer) {
+            GST_WARNING_OBJECT (submux, "checkbuffer null.. repop");
+            g_mutex_unlock (cur_stream->queue_lock);
+            goto re_pop;
+          }
+          if (!GST_BUFFER_DURATION (check_buffer)) {
+            GST_WARNING_OBJECT (submux, "duration of buffer is zero..re-pop");
+            gst_buffer_unref (check_buffer);
+            g_mutex_unlock (cur_stream->queue_lock);
+            goto re_pop;
+          }
+          submux->cur_buf_array[i] = check_buffer;
+          GST_DEBUG_OBJECT (submux, "consuming active stream [%d] buffer : ts = %"GST_TIME_FORMAT"and dur = %"GST_TIME_FORMAT,
+            i, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (check_buffer)), GST_TIME_ARGS(GST_BUFFER_DURATION (check_buffer)));
+        }
+      } else {
+        g_mutex_unlock (cur_stream->queue_lock);
+        GST_DEBUG_OBJECT(submux,"Coming to Else case submux->sinkpad %x ",submux->sinkpad);
+        continue;
+      }
+    } else {
+      GST_DEBUG_OBJECT (submux, "already received EOS on this stream[%d] and cur_buf_array[idx] = NULL", i);
+      submux->cur_buf_array[i] = NULL;
+    }
+
+    g_mutex_unlock (cur_stream->queue_lock);
+    GST_DEBUG_OBJECT (submux, "After unlocking in loop and signal queue full");
+  }
+
+  push_list = gst_submux_muxing (submux);
+  if (push_list) {
+    guint idx = 0;
+    GST_LOG_OBJECT (submux, "length of push list = %d", g_list_length (push_list));
+
+    for (idx = 0; idx < g_list_length (push_list); idx++) {
+      push_buf = g_list_nth_data (push_list, idx);
+
+      if (push_buf) {
+        GST_DEBUG_OBJECT (submux, "pushing buffer : ts = %"GST_TIME_FORMAT", "
+            "dur = %"GST_TIME_FORMAT" and data %s ...",
+        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (push_buf)),
+        GST_TIME_ARGS (GST_BUFFER_DURATION (push_buf)), (gchar*)GST_BUFFER_DATA (push_buf));
+
+        fret = gst_pad_push (submux->srcpad, push_buf);
+        if (fret != GST_FLOW_OK) {
+          GST_ERROR_OBJECT (submux, "failed to push buffer. reason : %s", gst_flow_get_name (fret));
+          /* clean any left buffers in push_list */
+          idx++;
+          for (; idx < g_list_length (push_list); idx++) {
+            push_buf = g_list_nth_data (push_list, idx);
+            gst_buffer_unref (push_buf);
+          }
+          g_list_free (push_list);
+          goto error;
+        }
+      }
+    }
+
+    g_list_free (push_list);
+  }
+
+  GST_DEBUG_OBJECT (submux, "Exiting from lopp in last");
+
+  return;
+
+eos_sent:
+error:
+  GST_WARNING_OBJECT (submux->srcpad, "Pausing the push task...");
+  if (fret < GST_FLOW_UNEXPECTED) {
+    GST_ERROR_OBJECT (submux, "Crtical error in push loop....");
+    GST_ELEMENT_ERROR (submux, CORE, PAD, ("failed to push. reason - %s", gst_flow_get_name (fret)), (NULL));
+  }
+  gst_pad_pause_task (submux->srcpad);
+  GST_DEBUG_OBJECT (submux, "Exiting from lopp in last");
+  return;
+}
+
+////////////////////////////////////////////////////////
+//        Plugin Utility Functions                    //
+////////////////////////////////////////////////////////
+/*
+**
+**  Description    : De-Initializing the submux private structure
+**  Params        : (1) submux instance
+**  return        : TRUE
+**  Comments    :
+**
+*/
+static gboolean
+gst_submux_deinit_private_values(Gstsubmux *submux)
+{
+  guint idx = 0;
+  GST_DEBUG_OBJECT (submux, "deinit priv values");
+
+  submux->priv->first_buffer = FALSE;
+  submux->priv->parser_type = 0;
+  if (submux->priv->lang_list && !submux->priv->is_internal) {
+    g_list_free (submux->priv->lang_list);
+    submux->priv->lang_list = NULL;
+  }
+  for (idx = 0; idx < submux->priv->stream_count; idx++) {
+    submux->cur_buf_array[idx] = NULL;
+  }
+  if (submux->cur_buf_array) {
+    g_free (submux->cur_buf_array);
+    submux->cur_buf_array = NULL;
+  }
+
+  submux->priv->is_internal = FALSE;
+  submux->priv->stream_count = 0;
+
+  return TRUE;
+}
+
+static gboolean
+gst_submux_plugin_init (GstPlugin * plugin)
+{
+  return gst_element_register (plugin, "submux", GST_RANK_PRIMARY, GST_TYPE_SUBMUX);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,GST_VERSION_MINOR,"submux","submux",gst_submux_plugin_init,"0.10.36","Proprietary","Samsung Electronics Co","http://www.samsung.com")
diff --git a/submux/src/gstsubmux.h b/submux/src/gstsubmux.h
new file mode 100755 (executable)
index 0000000..696b8b6
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * N-Project
+ * Copyright (c) 2008 Samsung Electronics, Inc.
+ * All rights reserved.
+ *
+ * This software is a confidential and proprietary information
+ * of Samsung Electronics, Inc. ("Confidential Information").  You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Samsung Electronics.
+ */
+
+/*
+ * This file defines the functions of Gstreamer plug-in for submux
+ *
+ * @file
+ * @author      Deepak Singh (deep.singh@samsung.com)
+ * @version     1.0
+ * @usage
+ * @brief       This plug-in is targeted to be used for ARM MP4ASP decoding.
+ */
+
+/*! Revision History:
+ *! ---------------------------------------------------------------------------
+ *!     DATE             |         AUTHOR               |       COMMENTS
+ *! ---------------------------------------------------------------------------
+ *! 17-Jan-2014            deep.singh@samsung.com              created
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <string.h>
+#include <gst/gst.h>
+#include <gst/gsterror.h>
+#include <glib.h>
+#include <gst/app/gstappsrc.h>
+#include <gst/app/gstappsink.h>
+#include <gst/base/gstadapter.h>
+G_BEGIN_DECLS
+
+#define GST_TYPE_SUBMUX        (gst_submux_get_type())
+#define GST_SUBMUX(obj)        (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SUBMUX,Gstsubmux))
+#define GST_SUBMUX_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SUBMUX,GstsubmuxClass))
+#define GST_SUBMUX_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_SUBMUX,GstsubmuxClass))
+#define GST_IS_SUBMUX(obj)     (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SUBMUX))
+#define GST_IS_SUBMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SUBMUX))
+#define GST_SUBMUX_CAST(obj)    ((Gstsubmux *)(obj))
+#define MAX_LANG 10
+
+typedef struct _Gstsubmux Gstsubmux;
+typedef struct _GstsubmuxClass GstsubmuxClass;
+typedef struct _GstsubmuxPrivate GstsubmuxPrivate;
+typedef struct _LanguageStruct  GstLangStruct;
+typedef struct _GstSubMuxStream GstSubmuxStream;
+typedef struct _GstSubMuxPipe SubMuxPipe;
+
+typedef enum
+{
+  GST_SUB_PARSE_FORMAT_UNKNOWN = 0,
+  GST_SUB_PARSE_FORMAT_MDVDSUB = 1,
+  GST_SUB_PARSE_FORMAT_SUBRIP = 2,
+  GST_SUB_PARSE_FORMAT_MPSUB = 3,
+  GST_SUB_PARSE_FORMAT_SAMI = 4,
+  GST_SUB_PARSE_FORMAT_TMPLAYER = 5,
+  GST_SUB_PARSE_FORMAT_MPL2 = 6,
+  GST_SUB_PARSE_FORMAT_SUBVIEWER = 7,
+  GST_SUB_PARSE_FORMAT_DKS = 8,
+  GST_SUB_PARSE_FORMAT_QTTEXT = 9
+} GstSubMuxFormat;
+typedef enum
+{
+  GST_SUB_PARSE_REGEX_UNKNOWN = 0,
+  GST_SUB_PARSE_REGEX_MDVDSUB = 1,
+  GST_SUB_PARSE_REGEX_SUBRIP = 2,
+  GST_SUB_PARSE_REGEX_DKS = 3,
+} GstSubMuxRegex;
+struct _GstSubMuxPipe
+{
+  GstElement *pipe;
+  GstElement *appsrc;
+  GstElement *appsink;
+  GstElement *parser;
+  GstPad *app_sinkpad;
+};
+struct _GstSubMuxStream
+{
+  void *parent;
+  gboolean need_segment;
+  gboolean discont_came;
+  gboolean flushing;
+  SubMuxPipe pipe_struc;
+  gboolean eos_sent;
+  gboolean eos_came;
+  GstClockTime duration;
+  GstClockTime last_ts; /* last timestamp of subtitle present in subtitle file*/
+  GstClockTime eos_ts;
+  GstClockTime seek_ts;
+  GstBuffer *buffer;
+  GQueue *queue;
+  GMutex *queue_lock;
+  GCond *queue_empty;
+  gboolean flush_done;
+};
+struct _Gstsubmux
+{
+    GstElement     element;
+
+    /*< private >*/
+    GstsubmuxPrivate *priv;
+
+    /* pads */
+    guint sinkpads_count;
+    gboolean external_sinkpad;
+    gboolean stop_loop;
+    GstPad *srcpad;
+    GList *sinkpad;
+    gboolean pipeline_made;
+    //GstPad *sinkpad;
+    GList *buffer_list;
+    gboolean init_done;
+    GList *msl_streams;
+    GList *streams;
+    gboolean flushing;
+    gboolean need_segment;
+    GstSubmuxStream muxed_stream;
+    gchar   *encoding;
+    gchar   *detected_encoding;
+    gint fps_n, fps_d;
+    GstSegment    segment;
+    GstTask *loop_task;
+    GstSeekFlags  segment_flags;
+    gboolean seek_came ;
+    gboolean finalize;
+    gboolean langlist_msg_posted;
+    GstBuffer **cur_buf_array;
+    gchar* external_filepath;
+};
+
+struct _GstsubmuxPrivate
+{
+    gboolean first_buffer;
+    GstSubMuxFormat parser_type;
+    GList *lang_list;
+    gboolean is_internal;
+    guint stream_count;
+};
+
+
+struct _LanguageStruct
+{
+    gchar *language_code;
+    gchar *language_key;
+    gboolean active;
+};
+
+struct _GstsubmuxClass
+{
+  GstElementClass parent_class;
+};
+
+GType           gst_submux_get_type         (void);
+
+G_END_DECLS
+
+
index 2ae6ac2..1f8d831 100755 (executable)
@@ -104,11 +104,9 @@ static void
 gst_mytoggle_class_init (GstMytoggleClass * klass)
 {
   GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
   GstBaseTransformClass *gstbasetrans_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
-  gstelement_class = GST_ELEMENT_CLASS (klass);
   gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
 
   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_mytoggle_set_property);
similarity index 100%
rename from avsystem/Makefile.am
rename to xvimagesrc/Makefile.am
diff --git a/xvimagesrc/src/Makefile.am b/xvimagesrc/src/Makefile.am
new file mode 100644 (file)
index 0000000..eff56f2
--- /dev/null
@@ -0,0 +1,26 @@
+# plugindir is set in configure
+
+##############################################################################
+# change libgstplugin.la to something more suitable, e.g. libmysomething.la  #
+##############################################################################
+plugin_LTLIBRARIES = libgstxvimagesrc.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
+libgstxvimagesrc_la_SOURCES = gstxvimagesrc.c
+
+# flags used to compile this plugin
+# add other _CFLAGS and _LIBS as needed
+libgstxvimagesrc_la_CFLAGS = $(GST_CFLAGS)  $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(TBM_CFLAGS) $(DRI2_CFLAGS) $(X11_CFLAGS) $(XEXT_CFLAGS) $(XV_CFLAGS) $(XDAMAGE_CFLAGS) $(DRM_DEVEL_CFLAGS) $(DRM_CFLAGS)
+libgstxvimagesrc_la_LIBADD = $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(TBM_LIBS) $(DRI2_LIBS) $(X11_LIBS) $(XEXT_LIBS) $(XV_LIBS) $(XDAMAGE_LIBS) $(DRM_LIBS) $(DRM_DEVEL_LIBS) $(DRM_SLP_MSM)
+libgstxvimagesrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+
+# headers we need but don't want installed
+noinst_HEADERS = gstxvimagesrc.h
diff --git a/xvimagesrc/src/gstxvimagesrc.c b/xvimagesrc/src/gstxvimagesrc.c
new file mode 100755 (executable)
index 0000000..1a29d62
--- /dev/null
@@ -0,0 +1,1832 @@
+/*
+ * xvimagesrc
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hyunil Park <hyunil46.park@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
+ *
+ */
+/**
+* SECTION:element-xvimagesrc
+*
+* xvimagesrc captures frame buffer which includes the application data along with video layer data
+* from the XServer and pushes the data to the downstream element.
+*
+*
+* <refsect2>
+* <title>Example launch line</title>
+* |[
+* gst-launch xvimagesrc ! "video/x-raw-yuv, width=720, height=1280, framerate=(fraction)30/1, format=(fourcc)ST12" ! fakesink
+* ]| captures the frame buffer from the XServer and send the buffers to a fakesink.
+* </refsect2>
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstxvimagesrc.h"
+
+/* headers for drm */
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <X11/Xmd.h>
+#include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#include <dri2.h>
+#include <drm.h>
+#include <exynos_drm.h>
+
+GST_DEBUG_CATEGORY_STATIC (xvimagesrc_debug);
+#define GST_CAT_DEFAULT xvimagesrc_debug
+
+
+#define GST_XV_IMAGE_SRC_CAPS                    \
+  "video/x-raw-rgb, "                            \
+  "bpp = (int) 32, "                             \
+  "depth = (int) 24, "                           \
+  "endianness = (int) BIG_ENDIAN, "              \
+  "red_mask = (int) 0xFF000000, "                \
+  "green_mask = (int) 0x00FF0000, "              \
+  "blue_mask = (int) 0x0000FF00, "               \
+  "width  = (int)  [ 16, 4096 ], "               \
+  "height = (int)  [ 16, 4096 ], "               \
+  "framerate = (fraction) [0/1, 2147483647/1];"  \
+  "video/x-raw-yuv,"                             \
+  "format = (fourcc) { SN12, ST12, NV12 }, "                 \
+  "width = (int) [ 1, 4096 ], "                  \
+  "height = (int) [ 1, 4096 ], "                 \
+  "framerate = (fraction) [0/1, 2147483647/1];"  \
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_STATIC_CAPS(GST_XV_IMAGE_SRC_CAPS)
+);
+
+enum
+{
+  PROP_0,
+  PROP_AUDIO_LATENCY,
+  PROP_SECURE_MODE,
+  PROP_DISPLAY_ROTATE,
+};
+
+enum
+{
+  VIDEO_TYPE_UI,
+  VIDEO_TYPE_VIDEO_WITH_UI,
+  VIDEO_TYPE_VIDEO_ONLY,
+};
+
+enum
+{
+  SIGNAL_UI_ONLY = 0,
+  SIGNAL_VIDEO_WITH_UI,
+  SIGNAL_VIDEO_ONLY,
+  SIGNAL_SELECTION_NOTIFY,
+  SIGNAL_LAST
+};
+
+#define GEM_NAME_MAX                10
+
+#define SCMN_CS_YUV420              1 /* Y:U:V 4:2:0 */
+#define SCMN_CS_I420                SCMN_CS_YUV420 /* Y:U:V */
+#define SCMN_CS_NV12                6
+#define SCMN_CS_NV12_T64X32         11 /* 64x32 Tiled NV12 type */
+#define SCMN_CS_UYVY                100
+#define SCMN_CS_YUYV                101
+#define SCMN_CS_YUY2                SCMN_CS_YUYV
+
+/* max channel count *********************************************************/
+#define SCMN_IMGB_MAX_PLANE         (4)
+
+/* image buffer definition ***************************************************
+
+    +------------------------------------------+ ---
+    |                                          |  ^
+    |     a[], p[]                             |  |
+    |     +---------------------------+ ---    |  |
+    |     |                           |  ^     |  |
+    |     |<---------- w[] ---------->|  |     |  |
+    |     |                           |  |     |  |
+    |     |                           |        |
+    |     |                           |  h[]   |  e[]
+    |     |                           |        |
+    |     |                           |  |     |  |
+    |     |                           |  |     |  |
+    |     |                           |  v     |  |
+    |     +---------------------------+ ---    |  |
+    |                                          |  v
+    +------------------------------------------+ ---
+
+    |<----------------- s[] ------------------>|
+*/
+
+typedef struct
+{
+  /* width of each image plane */
+  int w[SCMN_IMGB_MAX_PLANE];
+  /* height of each image plane */
+  int h[SCMN_IMGB_MAX_PLANE];
+  /* stride of each image plane */
+  int s[SCMN_IMGB_MAX_PLANE];
+  /* elevation of each image plane */
+  int e[SCMN_IMGB_MAX_PLANE];
+  /* user space address of each image plane */
+  void *a[SCMN_IMGB_MAX_PLANE];
+  /* physical address of each image plane, if needs */
+  void *p[SCMN_IMGB_MAX_PLANE];
+  /* color space type of image */
+  int cs;
+  /* left postion, if needs */
+  int x;
+  /* top position, if needs */
+  int y;
+  /* to align memory */
+  int __dummy2;
+  /* arbitrary data */
+  int data[16];
+  /* dmabuf fd */
+  gint32 fd[SCMN_IMGB_MAX_PLANE];
+  /* flag for buffer share */
+  int buf_share_method;
+  /* Y plane size in case of ST12 */
+  int y_size;
+  /* UV plane size in case of ST12 */
+  int uv_size;
+
+  /* Tizen buffer object of each image plane */
+  void *bo[SCMN_IMGB_MAX_PLANE];
+
+  /* JPEG data */
+  void *jpeg_data;
+  /* JPEG size */
+  int jpeg_size;
+
+  /* tzmem buffer */
+  int tz_enable;
+} SCMN_IMGB;
+
+typedef struct
+{
+  void  *address[GEM_NAME_MAX];
+  int buffer_size[GEM_NAME_MAX];
+  int name[GEM_NAME_MAX];
+  gint32 fd[GEM_NAME_MAX];
+  gint32 handle[GEM_NAME_MAX];
+} GEM_MMAP;
+
+typedef enum {
+ BUF_SHARE_METHOD_PADDR = 0,
+ BUF_SHARE_METHOD_FD
+} buf_share_method_t;
+
+typedef struct GstXvImageOutBuffer GstXvImageOutBuffer;
+
+struct GstXvImageOutBuffer {
+  GstBuffer buffer;
+  int fd_name;
+  int YBuf;
+  GstXVImageSrc * xvimagesrc;
+};
+
+
+
+#define DEFAULT_USER_AGENT           "GStreamer xvimagesrc "
+
+//#define _MAKE_DUMP
+#ifdef _MAKE_DUMP
+#define YUV_FRAME_SIZE 3110400
+#define YUV_720_FRAME_SIZE 1382400
+#define YUV_VGA_FRAME_SIZE 460800
+
+static int g_prev_frame[YUV_FRAME_SIZE] = {0,};
+static int g_dump_frame[100][YUV_720_FRAME_SIZE];
+//static int g_dump_frame[200][YUV_VGA_FRAME_SIZE];
+static int f_idx = 0;
+static int f_done = 0;
+#endif
+
+static guint gst_xv_image_src_signals[SIGNAL_LAST] = { 0 };
+
+//#define COUNT_FRAMES
+#ifdef COUNT_FRAMES
+gchar old_time[10] = {0, };
+#endif
+static gboolean error_caught = FALSE;
+
+#define HANDLE_OUTBUF_UNREF
+
+#ifdef HANDLE_OUTBUF_UNREF
+#define BUFFER_COND_WAIT_TIMEOUT            1000000
+#define GST_TYPE_GST_XV_IMAGE_OUT_BUFFER               (gst_xv_image_out_buffer_get_type())
+#define GST_IS_GST_XV_IMAGE_OUT_BUFFER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GST_XV_IMAGE_OUT_BUFFER))
+static GstBufferClass *gst_xv_image_out_buffer_parent_class = NULL;
+static void gst_xv_image_out_buffer_class_init(gpointer g_class, gpointer class_data);
+static void gst_xv_image_out_buffer_finalize(GstXvImageOutBuffer *buffer);
+static GstXvImageOutBuffer *gst_xv_image_out_buffer_new(GstXVImageSrc *src);
+#endif
+static GstStateChangeReturn gst_xv_image_src_change_state (GstElement * element, GstStateChange transition);
+static void gst_xv_image_src_finalize (GObject * gobject);
+
+static void gst_xv_image_src_set_property (GObject *object, guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_xv_image_src_get_property (GObject *object, guint prop_id, GValue * value, GParamSpec * pspec);
+static GstFlowReturn gst_xv_image_src_create (GstPushSrc * psrc, GstBuffer ** outbuf);
+static gboolean gst_xv_image_src_start (GstBaseSrc * bsrc);
+static gboolean gst_xv_image_src_stop (GstBaseSrc * bsrc);
+static gboolean gst_xv_image_src_get_size (GstBaseSrc * bsrc, guint64 * size);
+static gboolean gst_xv_image_src_is_seekable (GstBaseSrc * bsrc);
+static gboolean gst_xv_image_src_query (GstBaseSrc * bsrc, GstQuery * query);
+static gboolean gst_xv_image_src_unlock (GstBaseSrc * bsrc);
+static gboolean gst_xv_image_src_unlock_stop (GstBaseSrc * bsrc);
+static gboolean gst_xv_image_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
+
+static tbm_bufmgr bufmgr_get (Display *dpy, Pixmap pixmap);
+static int port_get (GstXVImageSrc * src, unsigned int id);
+static void pixmap_update (GstXVImageSrc * src,Display *dpy, tbm_bufmgr bufmgr, Pixmap pixmap,
+               int x, int y, int width, int height);
+static Pixmap pixmap_create (GstXVImageSrc * src, Display *dpy, int width, int height);
+
+static void* gst_xv_image_src_update_thread (void * asrc);
+static gboolean xvimagesrc_thread_start(GstXVImageSrc *src);
+static void drm_init(GstXVImageSrc *src);
+static void drm_finalize(GstXVImageSrc *src);
+static gint32 drm_convert_gem_to_fd(int * gemname_cnt, int drm_fd, unsigned int name,  void * data, void **virtual_address);
+static void gst_xv_get_image_sleep(void *asrc, long duration);
+
+static void
+_do_init (GType type)
+{
+  GST_DEBUG_CATEGORY_INIT (xvimagesrc_debug, "xvimagesrc", 0, "Xv image src");
+}
+
+GST_BOILERPLATE_FULL (GstXVImageSrc, gst_xv_image_src, GstPushSrc, GST_TYPE_PUSH_SRC, _do_init);
+
+#ifdef HANDLE_OUTBUF_UNREF
+static void gst_xv_image_out_buffer_class_init(gpointer g_class, gpointer class_data)
+{
+  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
+  gst_xv_image_out_buffer_parent_class = g_type_class_peek_parent(g_class);
+  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)gst_xv_image_out_buffer_finalize;
+}
+
+static GType gst_xv_image_out_buffer_get_type(void)
+{
+  static GType _gst_gst_xv_image_out_buffer_type;
+
+  if (G_UNLIKELY(_gst_gst_xv_image_out_buffer_type == 0)) {
+    static const GTypeInfo gst_xv_image_out_buffer_info = {
+      sizeof (GstBufferClass),
+      NULL,
+      NULL,
+      gst_xv_image_out_buffer_class_init,
+      NULL,
+      NULL,
+      sizeof (GstXvImageOutBuffer),
+      0,
+      NULL,
+      NULL
+    };
+    _gst_gst_xv_image_out_buffer_type = g_type_register_static(GST_TYPE_BUFFER,
+                                                        "GstOmxOutBuffer",
+                                                        &gst_xv_image_out_buffer_info, 0);
+  }
+  return _gst_gst_xv_image_out_buffer_type;
+}
+#ifdef DEBUG_BUFFER
+ int value[5] ={0};
+ static int value_count =0;
+#endif
+
+static GstStateChangeReturn
+gst_xv_image_src_change_state (GstElement * element, GstStateChange transition)
+{
+  GstXVImageSrc *src = GST_XV_IMAGE_SRC (element);
+
+  GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
+  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:
+    src->pause_cond_var = FALSE;
+    g_cond_signal(src->pause_cond);
+    break;
+  case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+    GST_WARNING("GST_STATE_CHANGE_PLAYING_TO_PAUSED: START");
+    src->pause_cond_var = TRUE;
+    g_cond_wait(src->pause_resp, src->pause_resp_lock);
+    GST_WARNING("GST_STATE_CHANGE_PLAYING_TO_PAUSED: End");
+    break;
+  case GST_STATE_CHANGE_PAUSED_TO_READY:
+    GST_WARNING("GST_STATE_CHANGE_PAUSED_TO_READY");
+    src->thread_return = TRUE;
+    g_cond_signal(src->pause_cond);
+    g_cond_signal(src->queue_cond);
+    break;
+  case GST_STATE_CHANGE_READY_TO_NULL:
+    break;
+  default :
+    break;
+  }
+  result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  return result;
+}
+
+
+static void gst_xv_image_out_buffer_finalize(GstXvImageOutBuffer *buffer)
+{
+  Atom atom_retbuf = 0;
+  if (buffer->xvimagesrc->thread_return) {
+    GST_INFO("xvimagesrc is being shutdown");
+    return;
+  }
+
+  g_mutex_lock (buffer->xvimagesrc->dpy_lock);
+  atom_retbuf = XInternAtom (buffer->xvimagesrc->dpy, "_USER_WM_PORT_ATTRIBUTE_RETURN_BUFFER", False);
+  XvSetPortAttribute (buffer->xvimagesrc->dpy, buffer->xvimagesrc->p, atom_retbuf, buffer->YBuf);  //data->YBuf is gemname, refer to drm_convert_gem_to_fd
+  g_mutex_unlock (buffer->xvimagesrc->dpy_lock);
+  g_cond_signal(buffer->xvimagesrc->buffer_cond);
+  GST_INFO(" xvimagesrc = %p, gem_name =%d, fd_name =%d", buffer->xvimagesrc, buffer->YBuf, buffer->fd_name);
+#ifdef DEBUG_BUFFER
+ int i = 0;
+ for(i=0 ; i<5; i++){
+   if (value[i] == buffer->YBuf) {
+     value[i]=0;
+     GST_ERROR("value[%d]=%d", i, value[i]);
+   }
+ }
+#endif
+  return;
+}
+
+
+static GstXvImageOutBuffer *gst_xv_image_out_buffer_new(GstXVImageSrc *src)
+{
+  GstXvImageOutBuffer *newbuf = NULL;
+  GST_LOG("gst_omx_out_buffer_new");
+
+  newbuf = (GstXvImageOutBuffer *)gst_mini_object_new(GST_TYPE_GST_XV_IMAGE_OUT_BUFFER);
+  if(!newbuf)
+  {
+    GST_ERROR("gst_omx_out_buffer_new out of memory");
+    return NULL;
+  }
+  GST_LOG("creating buffer : %p", newbuf);
+  newbuf->xvimagesrc = gst_object_ref(GST_OBJECT(src));
+  newbuf->fd_name = 0;
+  newbuf->YBuf =0;
+  return newbuf;
+}
+#endif
+
+static void
+gst_xv_image_src_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 (&srctemplate));
+  gst_element_class_set_details_simple (element_class, "XServer Display FB video source",
+    "Source/video",
+    "Receive frame buffer data from XServer and passes to next element",
+    "");
+}
+
+static void
+gst_xv_image_src_class_init (GstXVImageSrcClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstBaseSrcClass *gstbasesrc_class;
+  GstPushSrcClass *gstpushsrc_class;
+  GstElementClass *gstelement_class;
+  gobject_class = G_OBJECT_CLASS (klass);
+  gstelement_class = (GstElementClass *) klass;
+  gstbasesrc_class = (GstBaseSrcClass *) klass;
+  gstpushsrc_class = (GstPushSrcClass *) klass;
+  gobject_class->set_property = gst_xv_image_src_set_property;
+  gobject_class->get_property = gst_xv_image_src_get_property;
+  gobject_class->finalize = gst_xv_image_src_finalize;
+
+  gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_xv_image_src_start);
+  gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_xv_image_src_stop);
+  gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_xv_image_src_unlock);
+  gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_xv_image_src_unlock_stop);
+  gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_xv_image_src_get_size);
+  gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_xv_image_src_is_seekable);
+  gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_xv_image_src_query);
+  gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_xv_image_src_setcaps);
+  gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_xv_image_src_create);
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_xv_image_src_change_state);
+  g_object_class_install_property (gobject_class, PROP_DISPLAY_ROTATE,
+     g_param_spec_uint64 ("display-rotate",
+     "display-rotate",
+     "Display rotate info",
+     0, G_MAXUINT64, 0, G_PARAM_READWRITE));
+
+  gst_xv_image_src_signals[SIGNAL_UI_ONLY] =
+     g_signal_new ("ui-only", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+     G_STRUCT_OFFSET (GstXVImageSrcClass, ui_only), NULL, NULL,
+     g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+
+  gst_xv_image_src_signals[SIGNAL_VIDEO_WITH_UI] =
+     g_signal_new ("video-with-ui", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+     G_STRUCT_OFFSET (GstXVImageSrcClass, video_with_ui), NULL, NULL,
+     g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+
+  gst_xv_image_src_signals[SIGNAL_VIDEO_ONLY] =
+     g_signal_new ("video-only", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+     G_STRUCT_OFFSET (GstXVImageSrcClass, video_only), NULL, NULL,
+     g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+
+  gst_xv_image_src_signals[SIGNAL_SELECTION_NOTIFY] =
+     g_signal_new ("selection-notify", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+     G_STRUCT_OFFSET (GstXVImageSrcClass, selection_notify), NULL, NULL,
+     g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+}
+
+static gboolean gst_xv_image_src_get_frame_size(int fourcc, int width, int height, unsigned int *outsize)
+{
+  switch (fourcc) {
+/* case GST_MAKE_FOURCC('I','4','2','0'):      // V4L2_PIX_FMT_YUV420
+    *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
+    *outsize += 2 * ((GST_ROUND_UP_8 (width) / 2) * (GST_ROUND_UP_2 (height) / 2));
+    break;*/
+  case GST_MAKE_FOURCC('N','V','1','2'):       // V4L2_PIX_FMT_NV12 non-linear
+     GST_INFO("NV12");
+    *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
+    *outsize += (GST_ROUND_UP_4 (width) * height) / 2;
+    break;
+  case GST_MAKE_FOURCC('S','N','1','2'):       // V4L2_PIX_FMT_NV12 non-linear
+     GST_INFO("SN12");
+    *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
+    *outsize += (GST_ROUND_UP_4 (width) * height) / 2;
+    break;
+  case GST_MAKE_FOURCC('S','T','1','2'):       // V4L2_PIX_FMT_NV12 tiled non-linear
+     GST_INFO("ST12");
+    *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
+    *outsize += (GST_ROUND_UP_4 (width) * height) / 2;
+    break;
+  case GST_MAKE_FOURCC('R','G','B','4'):
+    /* jpeg size can't be calculated here. */
+    *outsize = width * height * 4;
+    break;
+  default:
+    /* unkown format!! */
+    *outsize = 0;
+    return FALSE;
+  }
+  return TRUE;
+}
+
+static gboolean
+gst_xv_image_src_parse_caps (const GstCaps * caps, guint32 *fourcc,
+  gint * width, gint * height, gint * rate_numerator, gint * rate_denominator, unsigned int *framesize)
+{
+  const GstStructure *structure;
+  GstPadLinkReturn ret = TRUE;
+  const GValue *framerate;
+  const char *media_type = NULL;
+  GST_DEBUG ("parsing caps");
+  if (gst_caps_get_size (caps) < 1) return FALSE;
+  GST_INFO("xvimagesrc src caps:%"GST_PTR_FORMAT, caps);
+  structure = gst_caps_get_structure (caps, 0);
+  ret = gst_structure_get_int (structure, "width", width);
+  if(!ret) {
+    GST_ERROR ("xvimagesrc width not specified in caps");
+    goto error;
+  }
+  ret = gst_structure_get_int (structure, "height", height);
+  if(!ret) {
+    GST_ERROR ("xvimagesrc height not specified in caps");
+    goto error;
+  }
+  media_type = gst_structure_get_name (structure);
+  if(media_type == NULL) {
+    GST_ERROR ("xvimagesrc media type not specified in caps");
+    goto error;
+  }
+  framerate = gst_structure_get_value (structure, "framerate");
+  if (framerate) {
+    *rate_numerator = gst_value_get_fraction_numerator (framerate);
+    *rate_denominator = gst_value_get_fraction_denominator (framerate);
+  } else {
+    GST_ERROR ("xvimagesrc frametype not specified in caps");
+    goto error;
+  }
+  if (g_strcmp0 (media_type, "video/x-raw-rgb") == 0) {
+    gst_xv_image_src_get_frame_size(FOURCC_RGB32, *width, *height, framesize);
+    *fourcc = FOURCC_RGB32;
+    GST_DEBUG ("Caps set to RGB32");
+  } else if(g_strcmp0 (media_type, "video/x-raw-yuv") == 0) {
+
+    GST_INFO ("media_type is video/x-raw-yuv");
+    guint32 format = FOURCC_SN12;
+    ret = gst_structure_get_fourcc (structure, "format", &format);
+    if (!ret) GST_DEBUG ("xvimagesrc format not specified in caps, SN12 selected as default");
+    ret = gst_xv_image_src_get_frame_size(format, *width, *height, framesize);
+    if(!ret) {
+      GST_ERROR ("xvimagesrc unsupported format type specified in caps");
+      goto error;
+    }
+    *fourcc = format;
+  }
+  return TRUE;
+/* ERRORS */
+error:
+    return FALSE;
+}
+
+static gboolean gst_xv_image_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
+{
+  gboolean res = TRUE;
+  gint width, height, rate_denominator, rate_numerator;
+  GstXVImageSrc *src;
+  src = GST_XV_IMAGE_SRC (bsrc);
+  res = gst_xv_image_src_parse_caps (caps, &src->format_id, &width, &height,
+    &rate_numerator, &rate_denominator, &src->framesize);
+  if (res) {
+    /* looks ok here */
+    src->width = width;
+    src->height = height;
+    src->rate_numerator = rate_numerator;
+    src->rate_denominator = rate_denominator;
+    GST_DEBUG_OBJECT (src, "size %dx%d, %d/%d fps",
+      src->width, src->height,
+      src->rate_numerator, src->rate_denominator);
+    if(src->rate_numerator)
+    {
+      src->sleep_base_time = (long) (((int)(1000/src->rate_numerator))*1000);
+      src->sleep_limit_time = (long) (-1*src->sleep_base_time);
+    }
+  }
+  xvimagesrc_thread_start(src);
+  return res;
+}
+static void
+gst_xv_image_src_reset (GstXVImageSrc * src)
+{
+}
+
+static void
+gst_xv_image_src_init (GstXVImageSrc * src, GstXVImageSrcClass * g_class)
+{
+  src->format_id = 0;
+  src->running_time = GST_CLOCK_TIME_NONE;
+  src->frame_duration = GST_CLOCK_TIME_NONE;
+  src->virtual = NULL;
+  src->bo = NULL;
+  src->dri2_buffers = NULL;
+  src->queue_lock = g_mutex_new ();
+  src->queue = g_queue_new ();
+  src->queue_cond = g_cond_new ();
+  src->cond_lock = g_mutex_new ();
+  src->buffer_cond = g_cond_new ();
+  src->buffer_cond_lock = g_mutex_new ();
+  src->pause_cond = g_cond_new ();
+  src->pause_cond_lock = g_mutex_new ();
+  src->pause_resp = g_cond_new ();
+  src->pause_resp_lock = g_mutex_new ();
+  src->dpy_lock = g_mutex_new ();
+  src->pause_cond_var = FALSE;
+  src->drm_fd = -1;
+  src->current_data_type = VIDEO_TYPE_VIDEO_WITH_UI;
+  src->new_data_type = VIDEO_TYPE_VIDEO_WITH_UI;
+  src->get_image_overtime = 0;
+  src->get_image_overtime_cnt = 0;
+  src->gemname_cnt = 0;
+  src->tz_enable = 0;
+  src->sleep_base_time = 0;
+  src->sleep_limit_time = 0;
+  src->switching_to_udp = FALSE;
+  drm_init(src);
+  gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
+}
+
+static void
+gst_xv_image_src_finalize (GObject * gobject)
+{
+  GstXVImageSrc *src = GST_XV_IMAGE_SRC (gobject);
+  GST_DEBUG_OBJECT (src, "finalize");
+  g_mutex_free (src->queue_lock);
+  drm_finalize(src);
+  G_OBJECT_CLASS (parent_class)->finalize (gobject);
+}
+static void drm_init(GstXVImageSrc *src)
+{
+  Display *dpy;
+  int eventBase, errorBase;
+  int dri2Major, dri2Minor;
+  char *driverName, *deviceName;
+  struct drm_auth auth_arg = {0};
+
+  src->drm_fd = -1;
+  dpy = XOpenDisplay(0);
+
+  /* DRI2 */
+  if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
+    GST_ERROR("DRI2QueryExtension !!");
+    return;
+  }
+  if (!DRI2QueryVersion(dpy, &dri2Major, &dri2Minor)) {
+   GST_ERROR("DRI2QueryVersion !!");
+   return;
+  }
+  if (!DRI2Connect(dpy, RootWindow(dpy, DefaultScreen(dpy)), &driverName, &deviceName)) {
+    GST_ERROR("DRI2Connect !!");
+    return;
+  }
+  GST_INFO("Open drm device : %s", deviceName);
+
+  /* get the drm_fd though opening the deviceName */
+  src->drm_fd = open(deviceName, O_RDWR);
+  if (src->drm_fd < 0) {
+    GST_ERROR("cannot open drm device (%s)", deviceName);
+    return;
+  }
+
+  /* get magic from drm to authentication */
+  if (ioctl(src->drm_fd, DRM_IOCTL_GET_MAGIC, &auth_arg)) {
+    GST_ERROR("cannot get drm auth magic");
+    close(src->drm_fd);
+    src->drm_fd = -1;
+    return;
+  }
+  if (!DRI2Authenticate(dpy, RootWindow(dpy, DefaultScreen(dpy)), auth_arg.magic)) {
+    GST_ERROR("cannot get drm authentication from X");
+    close(src->drm_fd);
+    src->drm_fd = -1;
+    return;
+  }
+}
+static void drm_finalize(GstXVImageSrc *src)
+{
+  if (src->drm_fd >= 0) {
+    close(src->drm_fd);
+    src->drm_fd = -1;
+  }
+}
+
+static gint32 drm_convert_gem_to_fd(int *gemname_cnt, int drm_fd, unsigned int name, void  *data, void **virtual_address)
+{
+  g_return_val_if_fail((data != NULL),0);
+  int count=0;
+  gint32 fd = 0;
+  count = *gemname_cnt;
+  GST_DEBUG("gamname_cnt = %d", count);
+  GST_DEBUG("name = %u", name);
+
+
+  GEM_MMAP *xv_gem_mmap = NULL;
+  xv_gem_mmap = (GEM_MMAP *) data;
+  if(count >=GEM_NAME_MAX)
+    goto PASS;
+
+  if (count < GEM_NAME_MAX ) {
+    int i =0;
+    for ( i =0 ; i < GEM_NAME_MAX ; i++) {
+      if (name == xv_gem_mmap->name[i])
+       goto PASS;
+    }
+
+    struct drm_prime_handle prime;
+    struct drm_gem_open gem_open;
+    struct drm_exynos_gem_mmap gem_mmap; //for virtual address
+
+    memset (&gem_open, 0, sizeof (struct drm_gem_open));
+    gem_open.name = name;
+    if (ioctl(drm_fd, DRM_IOCTL_GEM_OPEN, &gem_open)) {
+      GST_ERROR("Gem Open failed");
+      return 0;
+    }
+    memset (&prime, 0, sizeof (struct drm_prime_handle));
+    prime.handle = gem_open.handle;
+    prime.flags = DRM_CLOEXEC;
+    /*get gem_open handle*/
+    xv_gem_mmap->handle[count] = gem_open.handle;
+    GST_DEBUG("gem_open.handle =%d, xv_gem_mmap->handle[count]=%d", gem_open.handle, xv_gem_mmap->handle[count]);
+    /*get virtual address */
+    /*set name*/
+    xv_gem_mmap->name[count] = name;
+    memset (&gem_mmap, 0, sizeof (struct drm_exynos_gem_mmap));
+    gem_mmap.handle = prime.handle;
+    gem_mmap.size = gem_open.size;
+    /*set size*/
+    xv_gem_mmap->buffer_size[count] = gem_mmap.size;
+    if (drmIoctl(drm_fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &gem_mmap) !=0) {
+      GST_ERROR("Gem mmap failed [handle %d, size %d]", gem_mmap.handle, gem_mmap.size);
+      return 0;
+    }
+    /*set virtual address*/
+    xv_gem_mmap->address[count] = (void *)(gem_mmap.mapped);
+    GST_DEBUG ("%d - Virtual address[%d] = %p size=%d ", name, count, xv_gem_mmap->address[count],  xv_gem_mmap->buffer_size[count] );
+
+    /*get fd*/
+    if (ioctl(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime) < 0) {
+      GST_ERROR("Gem Handle to Fd failed");
+      return 0;
+    }
+    xv_gem_mmap->fd[count] = prime.fd;
+    GST_DEBUG("fd = %d", xv_gem_mmap->fd[count]);
+  }
+
+  if (count < GEM_NAME_MAX) {
+    count ++;
+    *gemname_cnt = count;
+  }
+
+PASS:
+
+  if (name == xv_gem_mmap->name[0]) {
+    *virtual_address = xv_gem_mmap->address[0];
+    fd = xv_gem_mmap->fd[0];
+  } else if (name == xv_gem_mmap->name[1]) {
+    *virtual_address = xv_gem_mmap->address[1];
+     fd = xv_gem_mmap->fd[1];
+  } else if (name == xv_gem_mmap->name[2]) {
+    *virtual_address = xv_gem_mmap->address[2];
+     fd = xv_gem_mmap->fd[2];
+  } else if ( name == xv_gem_mmap->name[3]) {
+    *virtual_address = xv_gem_mmap->address[3];
+     fd = xv_gem_mmap->fd[3];
+  } else if (name == xv_gem_mmap->name[4]) {
+    *virtual_address = xv_gem_mmap->address[4];
+     fd = xv_gem_mmap->fd[4];
+  } else if ( name == xv_gem_mmap->name[5]) {
+    *virtual_address = xv_gem_mmap->address[5];
+     fd = xv_gem_mmap->fd[5];
+  } else if (name == xv_gem_mmap->name[6]) {
+    *virtual_address = xv_gem_mmap->address[6];
+     fd = xv_gem_mmap->fd[6];
+  } else if (name == xv_gem_mmap->name[7]) {
+    *virtual_address = xv_gem_mmap->address[7];
+     fd = xv_gem_mmap->fd[7];
+  } else if ( name == xv_gem_mmap->name[8]) {
+    *virtual_address = xv_gem_mmap->address[8];
+     fd = xv_gem_mmap->fd[8];
+  } else if (name == xv_gem_mmap->name[9]) {
+    *virtual_address = xv_gem_mmap->address[9];
+     fd = xv_gem_mmap->fd[9];
+  }
+
+  GST_DEBUG("virtual_address = %p  fd = %d", *virtual_address, fd);
+  return fd;
+}
+
+static void
+gst_xv_image_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstXVImageSrc *src = GST_XV_IMAGE_SRC (object);
+  GST_INFO ("set property function %x", src);
+  switch (prop_id) {
+       case PROP_DISPLAY_ROTATE:
+               src->display_rotate = g_value_get_uint64 (value);
+               GST_DEBUG("display_rotate [%d]", src->display_rotate);
+               break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+  return;
+}
+
+static void
+gst_xv_image_src_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstXVImageSrc *src = GST_XV_IMAGE_SRC (object);
+  GST_INFO ("get property function %x", src);
+  switch (prop_id) {
+       case PROP_DISPLAY_ROTATE:
+               g_value_set_uint64 (value, src->display_rotate);
+               break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+static inline GstClockTime xvimagesrc_clock (GstXVImageSrc *src)
+{
+  struct timeval tv;
+  gettimeofday (&tv, NULL);
+  if(!src->base_time) {
+    src->base_time = GST_TIMEVAL_TO_TIME(tv);
+  }
+  return (GstClockTime)(GST_TIMEVAL_TO_TIME(tv) - src->base_time);
+}
+
+static gboolean gst_xv_image_src_get_timeinfo2(GstXVImageSrc *src, GstClockTime *time, GstClockTime *dur)
+{
+  int fps_nu = 0;
+  int fps_de = 0;
+  GstClockTime timestamp = GST_CLOCK_TIME_NONE;
+  GstClockTime duration = GST_CLOCK_TIME_NONE;
+  static GstClockTime prev_timestamp = 0;
+
+  GstClock *clock;
+  if (!src) {
+    GST_WARNING("Invalid pointer [handle:%p]", src);
+    return FALSE;
+  }
+  clock = gst_element_get_clock (GST_ELEMENT (src));
+  if (clock) {
+    timestamp = gst_clock_get_time (clock);
+    if(!gst_element_get_base_time (GST_ELEMENT(src)))
+      timestamp = GST_CLOCK_TIME_NONE;
+    else timestamp -= gst_element_get_base_time (GST_ELEMENT (src));
+    gst_object_unref (clock);
+  } else {
+    /* not an error not to have a clock */
+    timestamp = GST_CLOCK_TIME_NONE;
+  }
+
+  if ((timestamp - prev_timestamp <= 30000000) || (timestamp-prev_timestamp >=36000000)) {
+    //GST_ERROR("Gap is below 30ms or over 36ms!!");
+  }
+
+  /* if we have a framerate adjust timestamp for frame latency */
+  if ((int)((float)src->rate_numerator / (float)src->rate_denominator) <= 0) {
+    /*if fps is zero, auto fps mode*/
+    fps_nu = 0;
+    fps_de = 1;
+  } else {
+    fps_nu = 1;
+    fps_de = (int)((float)src->rate_numerator / (float)src->rate_denominator);
+  }
+  if (fps_nu > 0 && fps_de > 0) {
+    GstClockTime latency;
+    latency = gst_util_uint64_scale_int(GST_SECOND, fps_nu, fps_de);
+    duration = latency;
+  }
+  timestamp+=src->initial_audio_latency;
+  *time = timestamp;
+  *dur = duration;
+  prev_timestamp = timestamp;
+  return TRUE;
+}
+
+static gboolean gst_xv_image_src_get_timeinfo(GstXVImageSrc *src, GstBuffer *buffer)
+{
+  int fps_nu = 0;
+  int fps_de = 0;
+  GstClockTime timestamp = GST_CLOCK_TIME_NONE;
+  GstClockTime duration = GST_CLOCK_TIME_NONE;
+  GstClock *clock;
+  if (!src || !buffer) {
+    GST_WARNING("Invalid pointer [handle:%p, buffer:%p]", src, buffer);
+    return FALSE;
+  }
+  clock = gst_element_get_clock (GST_ELEMENT (src));
+  if (clock) {
+    timestamp = gst_clock_get_time (clock);
+    timestamp -= gst_element_get_base_time (GST_ELEMENT (src));
+    gst_object_unref (clock);
+  } else {
+    /* not an error not to have a clock */
+    timestamp = GST_CLOCK_TIME_NONE;
+  }
+
+  //timestamp = xvimagesrc_clock(src);
+  /* if we have a framerate adjust timestamp for frame latency */
+  if ((int)((float)src->rate_numerator / (float)src->rate_denominator) <= 0) {
+    /*if fps is zero, auto fps mode*/
+    fps_nu = 0;
+    fps_de = 1;
+  } else {
+    fps_nu = 1;
+    fps_de = (int)((float)src->rate_numerator / (float)src->rate_denominator);
+  }
+  if (fps_nu > 0 && fps_de > 0) {
+    GstClockTime latency;
+    latency = gst_util_uint64_scale_int(GST_SECOND, fps_nu, fps_de);
+    duration = latency;
+  }
+  GST_BUFFER_TIMESTAMP(buffer) = timestamp;
+  GST_BUFFER_DURATION(buffer) = duration;
+  return TRUE;
+}
+#ifdef COUNT_FRAMES
+static  int fps = 0;
+
+static gchar *get_current_system_time()
+{
+       gchar target[10]={0,};
+       time_t t;
+       struct tm tm;
+
+       t = time(NULL);
+       tzset();
+       /*localtimer_r : available since libc 5.2.5*/
+       if(localtime_r(&t, &tm) == NULL) {
+               return NULL;
+       }
+       snprintf(target, sizeof(target), "%02i:%02i:%02i", tm.tm_hour, tm.tm_min, tm.tm_sec);
+       return g_strdup(target);
+}
+#endif
+static void gst_xv_get_image_sleep(void *asrc, long duration)
+{
+    GST_INFO("end_time duration=%d", duration);
+    if (duration < 0) return;
+    GstXVImageSrc *src = (GstXVImageSrc *)asrc;
+    g_return_if_fail(src != NULL);
+    long sleep_time = 0;
+    sleep_time = src->sleep_base_time - duration;
+
+    if (sleep_time < 0) {
+         src->get_image_overtime_cnt ++;
+         src->get_image_overtime += sleep_time;
+         if (src->get_image_overtime_cnt > 2)
+           src->get_image_overtime = 0;
+         if (src->get_image_overtime <= src->sleep_limit_time)
+           src->get_image_overtime = 0;
+      //GST_WARNING("Over Time[%d] : %d", src->get_image_overtime_cnt, src->get_image_overtime);
+    } else if (sleep_time > 0) {
+      src->get_image_overtime_cnt = 0;
+         sleep_time = sleep_time + src->get_image_overtime;
+
+      if (src->get_image_overtime < 0) {
+        //GST_WARNING("Over Time : %d, So sleep time : %d", src->get_image_overtime, sleep_time);
+      }
+
+         src->get_image_overtime = (sleep_time < 0) ? sleep_time : 0;
+
+         if (sleep_time >0) {
+           GST_INFO("end_time : sleep_time = %d", sleep_time);
+        usleep(sleep_time);
+         }
+    }
+}
+static GstFlowReturn
+gst_xv_image_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
+{
+  GST_INFO("gst_xv_image_src_create");
+  GstXVImageSrc *src;
+  GstXvImageOutBuffer *outbuf = NULL;
+  src = GST_XV_IMAGE_SRC (psrc);
+  g_mutex_lock (src->queue_lock);
+  if(g_queue_is_empty (src->queue)) {
+    GST_INFO("g_queue_is_empty");
+    g_mutex_unlock (src->queue_lock);
+    GST_INFO("g_cond_wait");
+    g_cond_wait(src->queue_cond, src->cond_lock);
+    if(src->pause_cond_var) return GST_FLOW_WRONG_STATE;
+    g_mutex_lock (src->queue_lock);
+
+    if(src->switching_to_udp == TRUE) {
+      GstStructure *structure;
+      structure = gst_structure_new("Switch_udp", "switch_to_udp", G_TYPE_BOOLEAN, NULL, NULL);
+      GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, structure);
+      GstPad *srcpad = gst_element_get_static_pad(src, "src");
+      gst_pad_push_event(srcpad, event);
+      GST_INFO("sending the event");
+      src->switching_to_udp = FALSE;
+    }
+
+    outbuf = (GstXvImageOutBuffer *)g_queue_pop_head(src->queue);
+    GST_INFO("g_queue_pop_head");
+    g_mutex_unlock (src->queue_lock);
+  }
+  else {
+    GstXvImageOutBuffer *tempbuf = NULL;
+    if((tempbuf = (GstXvImageOutBuffer*)g_queue_pop_head(src->queue)) != NULL)
+    {
+      outbuf = tempbuf;    // To reduce latency, skipping the old frames and submitting only latest frames
+      g_mutex_unlock (src->queue_lock);
+    }
+    GST_INFO("g_queue_pop_head end");
+  }
+  if(outbuf == NULL) return GST_FLOW_ERROR;
+  GST_INFO("gem_name=%d, fd_name=%d, Time stamp of the buffer is %"GST_TIME_FORMAT, outbuf->YBuf, outbuf->fd_name, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(outbuf)));
+  *buffer = GST_BUFFER_CAST(outbuf);
+#ifdef COUNT_FRAMES
+    gchar *current_time = NULL;
+    current_time =     get_current_system_time();
+    if (strncmp(current_time, old_time, 10) == 0) {
+       fps ++;
+       strncpy(old_time, current_time, 10);
+    } else {
+       g_printf("xvimagesrc %s - fps : %d\n", old_time, fps);
+       fps = 1;
+       strncpy(old_time, current_time, 10);
+    }
+#endif
+  GST_INFO("return ok");
+  return GST_FLOW_OK;
+}
+
+static gboolean xvimagesrc_thread_start(GstXVImageSrc *src)
+{
+  GError *error;
+  if(!src->updates_thread) src->updates_thread = g_thread_create ((GThreadFunc) gst_xv_image_src_update_thread, src, TRUE, &error);
+  else GST_LOG_OBJECT (src, "The thread function already running");
+  return TRUE;
+}
+
+static gboolean
+gst_xv_image_src_start (GstBaseSrc * bsrc)
+{
+  GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
+  if(src->format_id) xvimagesrc_thread_start(src);
+  return TRUE;
+}
+
+gboolean signal_emit_func(void *asrc)
+{
+    GstXVImageSrc *src = (GstXVImageSrc *)asrc;
+
+   if (src->current_data_type == VIDEO_TYPE_UI) {
+     src->switching_to_udp = TRUE;
+     g_signal_emit (src, gst_xv_image_src_signals[SIGNAL_UI_ONLY] , 0, NULL);
+   } else if (src->current_data_type == VIDEO_TYPE_VIDEO_ONLY) {
+     g_signal_emit (src, gst_xv_image_src_signals[SIGNAL_VIDEO_ONLY] , 0, NULL);
+   } else if (src->current_data_type == VIDEO_TYPE_VIDEO_WITH_UI) {
+     g_signal_emit (src, gst_xv_image_src_signals[SIGNAL_VIDEO_WITH_UI] , 0, NULL);
+   }
+
+    return FALSE;
+}
+
+gboolean signal_selection_emit_func(void *asrc)
+{
+  GstXVImageSrc *src = (GstXVImageSrc *)asrc;
+
+  g_signal_emit (src, gst_xv_image_src_signals[SIGNAL_SELECTION_NOTIFY] , 0, NULL);
+
+  return FALSE;
+}
+
+static int
+gst_xvimagesrc_handle_xerror (Display * display, XErrorEvent * xevent)
+{
+  char error_msg[1024];
+
+  XGetErrorText (display, xevent->error_code, error_msg, 1024);
+  GST_DEBUG ("XError. error: %s", error_msg);
+  error_caught = TRUE;
+  return 0;
+}
+
+//static gboolean first_frame=TRUE;
+static int framecount=0;
+static void* gst_xv_image_src_update_thread (void * asrc)
+{
+  GstXVImageSrc *src = (GstXVImageSrc *)asrc;
+  Atom atom_data_type = 0;
+  Atom atom_secure = 0, atom_capture=0, atom_display=0;
+  Atom atom_fps = 0;
+  g_return_val_if_fail((src != NULL),NULL);
+  int i=0;
+  struct drm_gem_close gem_close;
+  GEM_MMAP *xv_gem_mmap = NULL;
+  xv_gem_mmap = (GEM_MMAP *)malloc(sizeof(GEM_MMAP));
+  g_return_val_if_fail((xv_gem_mmap != NULL),NULL);
+
+  memset(xv_gem_mmap, 0, sizeof(GEM_MMAP));
+
+  GST_LOG_OBJECT (src, "The thread function start");
+  {
+    int damage_err_base = 0;
+    Atom atom_format = 0;
+    src->dpy = XOpenDisplay (NULL);
+    src->p = port_get (src, src->format_id);
+    if (src->p < 0) goto finish;
+    /*src->width and src->height is set by caps info */
+    GST_DEBUG (" width and height of caps : %dx%d ", src->width, src->height);
+    if (src->width == 0 || src->height == 0) goto finish;
+    GST_DEBUG ("gst_xv_image_src_update_thread pixmap_create !!");
+    src->pixmap = pixmap_create (src, src->dpy, src->width, src->height);
+    GST_DEBUG ("gst_xv_image_src_update_thread pixmap_create !!");
+    src->gc = XCreateGC (src->dpy, src->pixmap, 0, 0);
+    GST_DEBUG ("gst_xv_image_src_update_thread XCreateGC !!");
+    src->bufmgr = bufmgr_get (src->dpy, src->pixmap);
+    if (!src->bufmgr) goto finish;
+    GST_DEBUG ("gst_xv_image_src_update_thread bufmgr_get !!");
+    if (!XDamageQueryExtension(src->dpy, &src->damage_base, &damage_err_base)) goto finish;
+    GST_DEBUG ("gst_xv_image_src_update_thread XDamageQueryExtension !!");
+    src->damage = XDamageCreate (src->dpy, src->pixmap, XDamageReportNonEmpty);
+    atom_format = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_FORMAT", False);
+    atom_capture = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", False);
+    atom_display = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_DISPLAY", False);
+
+    /*get data type*/
+    atom_data_type = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_DATA_TYPE", False);
+    /* _USER_WM_PORT_ATTRIBUTE_STREAM_OFF is removed */
+    //src->atom_stream_off = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", False);
+
+    XvSetPortAttribute (src->dpy, src->p, atom_format, src->format_id);
+    XvSetPortAttribute (src->dpy, src->p, atom_capture, 2);
+    XvSetPortAttribute (src->dpy, src->p, atom_display, 1);
+
+    XvSelectPortNotify (src->dpy, src->p, 1);
+    XvGetPortAttribute (src->dpy, src->p, atom_data_type, &(src->new_data_type));
+
+
+    /* Set display type */
+    Atom atom_select_display=0;
+    Atom atom_select_display_type=0;
+    Atom atom_encoding=0;
+    XTextProperty xtp;
+    const char *display_type = "WFD";
+
+    atom_select_display = XInternAtom(src->dpy, "SEL_EXT_DISPLAY", False);
+    atom_select_display_type = XInternAtom(src->dpy, "SEL_EXT_DISPLAY_TYPE", False);
+    atom_encoding = XInternAtom(src->dpy, "UTF8_STRING", False);
+    src->win = DefaultRootWindow(src->dpy);
+
+    XSetSelectionOwner(src->dpy, atom_select_display, src->win, 0);
+
+    xtp.value = (unsigned char *)display_type;
+    xtp.format = 8;
+    xtp.encoding = atom_encoding;
+    xtp.nitems = strlen(display_type);
+    XSetTextProperty(src->dpy, src->win, &xtp, atom_select_display_type);
+  }
+
+  struct timeval start_time, end_time;
+  long duration;
+  long starttime, endtime;
+  GTimeVal timeout;
+  XEvent ev;
+  int eventcount = 0;
+  int refresh = 1;
+  void *virtual_address = NULL;
+  int (*handler) (Display *, XErrorEvent *);
+  GstXvImageOutBuffer *outbuf = NULL;
+
+  GstClockTime ts_putstill = 0;
+  GstClockTime dur_putstill = 0;
+
+  gboolean got_display_select_req = FALSE;
+
+  while(!src->thread_return) {
+    if(src->pause_cond_var == TRUE) {
+      GST_WARNING("PAUSED in thread");
+      g_cond_signal(src->pause_resp);
+      g_cond_wait(src->pause_cond,src->pause_cond_lock);
+    }
+
+    if (src->thread_return) {
+      GST_WARNING("Thread return");
+      break;
+    }
+
+    if (refresh == 1) {
+      duration = 0;
+      starttime =0;
+      endtime = 0;
+      start_time.tv_sec = 0;
+      start_time.tv_usec = 0;
+      end_time.tv_sec   = 0;
+      end_time.tv_usec = 0;
+      gettimeofday(&start_time, NULL);
+      refresh = 0;
+    }
+
+    eventcount = 0;
+    virtual_address = NULL;
+    duration = 0;
+    outbuf = NULL;
+    g_mutex_lock (src->dpy_lock);
+    GST_DEBUG("[XCALL] call XSync");
+    XSync(src->dpy, 0);
+    GST_INFO ("gst_xv_image_src_update_thread XSync@@ !!");
+    g_mutex_unlock (src->dpy_lock);
+    error_caught = FALSE;
+    //GST_DEBUG ("gst_xv_image_src_update_thread XSetErrorHandler in !!");
+    handler = XSetErrorHandler (gst_xvimagesrc_handle_xerror);
+    //GST_INFO ("gst_xv_image_src_update_thread XSetErrorHandler !!");
+    //GST_INFO ("gst_xv_image_src_update_thread XvPutStill in !!");
+    g_mutex_lock (src->dpy_lock);
+    GST_DEBUG("[XCALL] call XvPutStill");
+    XvPutStill (src->dpy, src->p, src->pixmap, src->gc, 0, 0, src->width, src->height, 0, 0, src->width, src->height);
+
+    gst_xv_image_src_get_timeinfo2(src, &ts_putstill, &dur_putstill);
+
+    //GST_INFO ("gst_xv_image_src_update_thread XvPutStill !!");
+    GST_DEBUG("[XCALL] call 2nd XSync");
+    XSync (src->dpy, 0);
+    GST_DEBUG("[XCALL] call 2nd XSync done");
+    g_mutex_unlock (src->dpy_lock);
+    if (error_caught) {
+      GST_ERROR("gst_xv_image_src_update_thread error_caught is TRUE, X is out of buffers");
+           error_caught = FALSE;
+           XSetErrorHandler(handler);
+      g_get_current_time(&timeout);
+      g_time_val_add(&timeout, BUFFER_COND_WAIT_TIMEOUT);
+      if(!g_cond_timed_wait(src->buffer_cond, src->buffer_cond_lock, &timeout)) {
+             GST_ERROR("skip wating");
+      } else {
+         GST_ERROR("Signal received");
+      }
+      continue;
+    }
+    /*reset error handler*/
+    error_caught = FALSE;
+    XSetErrorHandler(handler);
+
+    //GST_INFO ("gst_xv_image_src_update_thread XSync !!");
+next_event:
+    g_mutex_lock (src->dpy_lock);
+    //GST_INFO("XNextEvent in");
+    XNextEvent (src->dpy, &ev); /* wating for x event */
+    //GST_INFO("XNextEvent out");
+    g_mutex_unlock (src->dpy_lock);
+    //GST_INFO ("gst_xv_image_src_update_thread XNextEvent !!");
+    if (ev.type == (src->damage_base + XDamageNotify)) {
+      XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&ev;
+      GST_INFO ("gst_xv_image_src_update_thread XDamageNotifyEvent");
+      g_mutex_lock (src->dpy_lock);
+      if (damage_ev->drawable == src->pixmap) {
+        pixmap_update (src, src->dpy, src->bufmgr, src->pixmap,
+        damage_ev->area.x,
+        damage_ev->area.y,
+        damage_ev->area.width,
+        damage_ev->area.height);
+             GST_INFO("gst_xv_image_src_update_thread pixmap_update");
+      }
+      XDamageSubtract (src->dpy, src->damage, None, None );
+      g_mutex_unlock (src->dpy_lock);
+      GST_INFO ("gst_xv_image_src_update_thread XDamageSubtract");
+    }
+    /* Added to handle display selection notify */
+    else if (ev.type == SelectionClear) {
+      XSelectionEvent *selection_ev = (XSelectionEvent*)&ev;
+
+      GST_ERROR("ev.type : %d SelectionClear", ev.type);
+      //g_timeout_add(1, signal_selection_emit_func, src);
+    }
+    else if (ev.type == SelectionRequest) {
+      XSelectionRequestEvent *selection_ev = (XSelectionRequestEvent*)&ev;
+
+      GST_ERROR("ev.type : %d SelectionRequest", ev.type);
+      src->requestor = selection_ev->requestor;
+      src->selection = selection_ev->selection;
+      src->target = selection_ev->target;
+      src->property = selection_ev->property;
+
+      got_display_select_req = TRUE;
+      g_timeout_add(1, signal_selection_emit_func, src);
+    }
+    else if (ev.type == SelectionNotify) {
+      XSelectionEvent *selection_ev = (XSelectionEvent*)&ev;
+
+      GST_ERROR("ev.type : %d SelectionNotify", ev.type);
+      //g_timeout_add(1, signal_selection_emit_func, src);
+    }
+    else if (ev.type == (src->evt_base + XvPortNotify)) {
+      XvPortNotifyEvent *notify_ev = (XvPortNotifyEvent*)&ev;
+      if (notify_ev->attribute == atom_secure) {
+          GST_WARNING ("secure attr changed : %s \n", ((int)notify_ev->value)?"Secure":"Normal");
+          src->tz_enable = (int)notify_ev->value;
+          GST_ERROR("src->tz_enable = %d", src->tz_enable);
+      }
+      else
+      if (notify_ev->attribute == atom_data_type) {
+        /* got a port notify, data_type */
+        src->new_data_type = (int)notify_ev->value;
+        if (src->current_data_type != src->new_data_type) {
+          src->current_data_type = src->new_data_type;
+          //GST_WARNING("current_data_type : %s \n", (src->current_data_type)?"Video":"UI+Video");
+          if (src->current_data_type == VIDEO_TYPE_UI) {
+            GST_WARNING("current_data_type : UI\n");
+          } else if (src->current_data_type == VIDEO_TYPE_VIDEO_WITH_UI) {
+            GST_WARNING("current_data_type : Video+UI\n");
+          } else if (src->current_data_type == VIDEO_TYPE_VIDEO_ONLY) {
+            GST_WARNING("current_data_type : VideoOnly\n");
+          }
+
+          g_timeout_add(1, signal_emit_func, src);
+        }
+      }
+      goto next_event;
+    }
+
+    if(!src->virtual) continue;
+    if(src->format_id == FOURCC_RGB32) {
+      outbuf = (GstXvImageOutBuffer*)gst_buffer_new_and_alloc (src->framesize);
+      gst_buffer_set_caps (GST_BUFFER_CAST(outbuf), GST_PAD_CAPS (GST_BASE_SRC_PAD (src)));
+      memcpy(GST_BUFFER_DATA (outbuf), src->virtual, src->framesize);
+    } else if ((src->format_id == FOURCC_SN12) || (src->format_id == FOURCC_NV12)) {
+      XV_DATA_PTR data = (XV_DATA_PTR)src->virtual;
+      int error = XV_VALIDATE_DATA (data);
+      outbuf = gst_xv_image_out_buffer_new(src);
+      if(!outbuf)
+      {
+        GST_ERROR("Out of memory");
+        continue;
+      }
+      gst_buffer_set_caps (GST_BUFFER_CAST(outbuf), GST_PAD_CAPS (GST_BASE_SRC_PAD (src)));
+      if (error == XV_HEADER_ERROR)
+        GST_ERROR ("XV_HEADER_ERROR\n");
+      else if (error == XV_VERSION_MISMATCH)
+        GST_ERROR ("XV_VERSION_MISMATCH\n");
+      else
+      {
+        SCMN_IMGB *psimgb = NULL;
+        psimgb = (SCMN_IMGB *)malloc(sizeof(SCMN_IMGB));
+        if (psimgb == NULL) {
+          GST_ERROR_OBJECT(src, "failed to alloc SCMN_IMGB");
+          return NULL;
+        }
+        memset(psimgb, 0x00, sizeof(SCMN_IMGB));
+        if (data->BufType == XV_BUF_TYPE_LEGACY) {
+          psimgb->p[0] = (void *)data->YBuf;
+          psimgb->p[1] = (void *)data->CbBuf;
+          psimgb->buf_share_method = BUF_SHARE_METHOD_PADDR;
+          psimgb->a[0] = NULL;
+          psimgb->a[1] = NULL;
+        } else if (data->BufType == XV_BUF_TYPE_DMABUF) {
+          psimgb->fd[0] = drm_convert_gem_to_fd(&src->gemname_cnt, src->drm_fd, (void *)data->YBuf, xv_gem_mmap, &virtual_address);
+          if(!virtual_address) {
+            free(psimgb);
+            psimgb = NULL;
+            continue;
+          }
+          psimgb->a[0] = virtual_address;
+          GST_DEBUG("YBuf gem to fd[0]=%d virtual_address = %p", psimgb->fd[0], psimgb->a[0]);
+          psimgb->fd[1] = drm_convert_gem_to_fd(&src->gemname_cnt, src->drm_fd, (void *)data->CbBuf, xv_gem_mmap, &virtual_address);
+          if(!virtual_address) {
+            free(psimgb);
+            psimgb = NULL;
+            continue;
+          }
+          psimgb->a[1] = virtual_address;
+          GST_DEBUG("CbBuf gem to fd[1]=%d  virtual_address = %p", psimgb->fd[1], psimgb->a[1]);
+          psimgb->buf_share_method = BUF_SHARE_METHOD_FD;
+          psimgb->w[1] = src->width;
+          psimgb->h[1] = src->height >> 1;
+          psimgb->s[1] = GST_ROUND_UP_16(psimgb->w[1]);
+          psimgb->e[1] = GST_ROUND_UP_16(psimgb->h[1]);
+          psimgb->cs   = SCMN_CS_NV12;
+          psimgb->tz_enable = 0;
+        }
+        psimgb->w[0] = src->width;
+        psimgb->h[0] = src->height;
+        psimgb->s[0] = GST_ROUND_UP_16(psimgb->w[0]);
+        psimgb->e[0] = GST_ROUND_UP_16(psimgb->h[0]);
+        outbuf->fd_name = psimgb->fd[0];
+        GST_BUFFER_MALLOCDATA(outbuf) = (unsigned char*)psimgb;
+        GST_BUFFER_DATA(outbuf) = src->virtual;
+        outbuf->YBuf = data->YBuf;
+           outbuf->fd_name = psimgb->fd[0];
+#ifdef DEBUG_BUFFER
+        for ( i=0; i<5 ; i++) {
+         if(value[value_count] == outbuf->YBuf ) {
+           GST_ERROR("ERROR: value[%d](%d)==YBUf(%d)", value_count, value[value_count], outbuf->YBuf);
+         }
+        }
+        value[value_count] = outbuf->YBuf ;
+           GST_ERROR("value[%d]=%d", value_count, value[value_count]);
+           if( value_count < 4){
+             value_count ++;
+           } else {
+             value_count = 0;
+           }
+#endif
+
+#ifdef _MAKE_DUMP
+      if (f_idx < 100) {
+        if (src->running_time > 14000000000 && src->running_time < 20000000000)  {
+          GST_ERROR("Mem copy");
+          if (virtual_address == NULL) {
+          GST_ERROR("Mem virtual is NULL[%d]", f_idx);
+          } else {
+          memcpy(g_dump_frame[f_idx++], virtual_address, YUV_720_FRAME_SIZE);
+          //memcpy(g_dump_frame[f_idx++], virtual_address, YUV_VGA_FRAME_SIZE);
+          GST_ERROR("Mem copy done[%d]", f_idx);
+          }
+        }
+      } else {
+      if (f_done == 0) {
+        GST_ERROR("File DUMP!!");
+        FILE *fp = NULL;
+        fp = fopen("/opt/usr/media/Videos/frame.yuv", "a");
+        int i = 0;
+        for (i = 0; i < 100; i++) {
+          fwrite(g_dump_frame[i], YUV_720_FRAME_SIZE, 1, fp);
+          //fwrite(g_dump_frame[i], YUV_VGA_FRAME_SIZE, 1, fp);
+        }
+        fclose(fp);
+        f_done = 1;
+        GST_ERROR("File DUMP done!!");
+      }
+      }
+#endif
+      }
+    }
+  if(!outbuf) continue;
+       GST_BUFFER_SIZE (outbuf) = src->framesize;
+    //gst_xv_image_src_get_timeinfo(src, GST_BUFFER_CAST(outbuf));
+    GST_BUFFER_TIMESTAMP(outbuf) = ts_putstill;
+    GST_BUFFER_DURATION(outbuf) = dur_putstill;
+    src->running_time = GST_BUFFER_TIMESTAMP(outbuf);
+    src->frame_duration = GST_BUFFER_DURATION(outbuf);
+    //first_frame = FALSE;
+    g_mutex_lock (src->queue_lock);
+    g_queue_push_tail(src->queue, outbuf);
+    //GST_INFO("g_queue_push_tail");
+    g_mutex_unlock (src->queue_lock);
+    g_cond_signal(src->queue_cond);
+    //GST_INFO("g_cond_signal");
+
+    update_done:
+      if (src->virtual) tbm_bo_unmap(src->bo);
+      src->virtual = NULL;
+      GST_INFO("g_cond_signal");
+      if (src->bo) tbm_bo_unref(src->bo);
+      src->bo = NULL;
+      if (src->dri2_buffers) free(src->dri2_buffers);
+      src->dri2_buffers = NULL;
+      gettimeofday(&end_time, NULL);
+      starttime = start_time.tv_usec;
+      endtime =  end_time.tv_usec;
+      //GST_INFO("star_time: %d, end_time:%d", starttime, endtime);
+      if (endtime > starttime) {
+        //GST_INFO("end_time > start_time");
+        duration = endtime - starttime;
+         } else {
+           //GST_INFO("end_time.tv_usec < start_time.tv_usec");
+           endtime=endtime+1000000;
+           //GST_INFO("end_time =%d", endtime);
+        duration = endtime -starttime;
+      }
+
+      GST_INFO("end_time duration = %d", duration);
+      //if (src->sleep_base_time > duration)
+        gst_xv_get_image_sleep (src, duration);
+
+      refresh = 1;
+      GST_INFO("gst_xv_image_src_update_thread cleanup !!");
+  }
+  GST_WARNING("gst_xv_image_src_update_thread loop ended");
+
+  for ( i=0 ; i < GEM_NAME_MAX ; i++) {
+    /*gem munmap*/
+    if (xv_gem_mmap->address[i]) {
+      if (-1 == munmap(xv_gem_mmap->address[i],xv_gem_mmap->buffer_size[i])) {
+        GST_ERROR ("munmap failed");
+        return NULL;
+      }
+    }
+    if (xv_gem_mmap->handle[i]) {
+       gem_close.handle = xv_gem_mmap->handle[i];
+       if (ioctl(src->drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close)) {
+         GST_ERROR("Gem Close failed");
+       }
+    }
+    if (xv_gem_mmap->fd[i]) {
+      close(xv_gem_mmap->fd[i]);
+    }
+  }
+  if (xv_gem_mmap) {
+    free(xv_gem_mmap);
+    xv_gem_mmap = NULL;
+  }
+  GST_LOG_OBJECT (src, "The thread function cleanup");
+
+  XvStopVideo(src->dpy, src->p, src->pixmap);
+
+  if (src->bufmgr) {
+    tbm_bufmgr_deinit (src->bufmgr);
+    src->bufmgr = NULL;
+  }
+  if (src->p > 0) {
+    XvUngrabPort (src->dpy, src->p, 0);
+    src->p = 0;
+  }
+
+  if (got_display_select_req) {
+  /* Notify miracast-destroyed to X  */
+  GST_WARNING_OBJECT (src, "There is display selection request");
+  XEvent xev;
+  XSelectionEvent xnotify;
+
+  xnotify.type = SelectionNotify;
+  xnotify.display = src->dpy;
+  xnotify.requestor = src->requestor;
+  xnotify.selection = src->selection;
+  xnotify.target = src->target;
+  xnotify.property = src->property;
+  xnotify.time = 0;
+  xnotify.send_event = True;
+  xnotify.serial = 0;
+  xev.xselection = xnotify;
+  if (XSendEvent(src->dpy, src->requestor, False, 0, &xev) < 0) {
+    GST_ERROR("XSendEvent failed!");
+  } else {
+    GST_INFO("XSendEvent success!");
+  }
+  }
+
+  if (src->gc) {
+    XFreeGC (src->dpy, src->gc);
+    src->gc = NULL;
+  }
+  if (src->pixmap > 0) {
+    XFreePixmap (src->dpy, src->pixmap);
+    src->pixmap = 0;
+  }
+  if (src->dpy) {
+    XCloseDisplay (src->dpy);
+    src->dpy = NULL;
+  }
+
+  GST_LOG_OBJECT (src, "The thread function stop");
+  return NULL;
+finish:
+  GST_LOG_OBJECT (src, "The thread function Error cleanup");
+
+  XvStopVideo(src->dpy, src->p, src->pixmap);
+
+  if (src->bufmgr) tbm_bufmgr_deinit (src->bufmgr);
+  src->bufmgr = NULL;
+  if (src->p > 0) XvUngrabPort (src->dpy, src->p, 0);
+  src->p = 0;
+  if (src->gc) XFreeGC (src->dpy, src->gc);
+  src->gc = NULL;
+  if (src->pixmap > 0) XFreePixmap (src->dpy, src->pixmap);
+  src->pixmap = 0;
+  if (src->dpy) XCloseDisplay (src->dpy);
+  src->dpy = NULL;
+  GST_LOG_OBJECT (src, "The thread function Error stop");
+  return NULL;
+}
+
+static tbm_bufmgr bufmgr_get (Display *dpy, Pixmap pixmap)
+{
+  int screen;
+  int drm_fd;
+  tbm_bufmgr bufmgr;
+  int eventBase, errorBase;
+  int dri2Major, dri2Minor;
+  char *driverName = NULL, *deviceName = NULL;
+  drm_magic_t magic;
+
+  screen = DefaultScreen(dpy);
+  if (!DRI2QueryExtension (dpy, &eventBase, &errorBase)) {
+    GST_ERROR ("!!Error : DRI2QueryExtension !!");
+    return NULL;
+  }
+  if (!DRI2QueryVersion (dpy, &dri2Major, &dri2Minor)) {
+    GST_ERROR ("!!Error : DRI2QueryVersion !!");
+    return NULL;
+  }
+  if (!DRI2Connect (dpy, RootWindow(dpy, screen), &driverName, &deviceName)) {
+    GST_ERROR ( "!!Error : DRI2Connect !!");
+    if(driverName) Xfree(driverName);
+    if(deviceName) Xfree(deviceName);
+    return NULL;
+  }
+
+  if(driverName) Xfree(driverName);
+  if(!deviceName) return NULL;
+
+  GST_DEBUG("Open drm device : %s", deviceName);
+  // get the drm_fd though opening the deviceName
+  drm_fd = open (deviceName, O_RDWR);
+  if (drm_fd < 0) {
+    GST_ERROR ("!!Error : cannot open drm device (%s)", deviceName);
+    if(deviceName) Xfree(deviceName);
+    return NULL;
+  }
+  if(deviceName) Xfree(deviceName);
+  /* get the drm magic */
+  drmGetMagic(drm_fd, &magic);
+  fprintf(stderr, ">>> drm magic=%d \n", magic);
+  if (!DRI2Authenticate(dpy, RootWindow(dpy, screen), magic))
+  {
+    fprintf(stderr, "!!Error : DRI2Authenticate !!\n");
+    close (drm_fd);
+    return NULL;
+  }
+  // drm slp buffer manager init
+  bufmgr = tbm_bufmgr_init (drm_fd);
+  if (!bufmgr) {
+    GST_ERROR ("!!Error : fail to init buffer manager ");
+    close (drm_fd);
+    return NULL;
+  }
+  DRI2CreateDrawable (dpy, pixmap);
+  close (drm_fd);
+  return bufmgr;
+}
+
+static int port_get (GstXVImageSrc * src, unsigned int id)
+{
+  unsigned int ver, rev, req_base, err_base;
+  unsigned int adaptors;
+  XvAdaptorInfo *ai = NULL;
+  XvAttribute *at = NULL;
+  XvImageFormatValues *fo = NULL;
+  int attributes, formats;
+  int i, j, p;
+
+  if (XvQueryExtension (src->dpy, &ver, &rev, &req_base, &src->evt_base, &err_base) != Success) return -1;
+  if (XvQueryAdaptors (src->dpy, DefaultRootWindow (src->dpy), &adaptors, &ai) != Success) return -1;
+  if (!ai) return -1;
+  for (i = 0; i < adaptors; i++) {
+    int support_format = False;
+    if (!(ai[i].type & XvInputMask) || !(ai[i].type & XvStillMask)) continue;
+    GST_LOG ("===========================================");
+    GST_LOG (" name:        %s"
+                " first port:  %ld"
+                " ports:       %ld",
+                ai[i].name,
+                ai[i].base_id,
+                ai[i].num_ports);
+    p = ai[i].base_id;
+    GST_LOG (" attribute list:");
+    at = XvQueryPortAttributes (src->dpy, p, &attributes);
+    for (j = 0; j < attributes; j++) GST_LOG ("\t-  name: %s\n"
+                    "\t\t  flags:     %s%s\n"
+                    "\t\t  min_value:  %i\n"
+                    "\t\t  max_value:  %i\n",
+                    at[j].name,
+                    (at[j].flags & XvGettable) ? " get" : "",
+                    (at[j].flags & XvSettable) ? " set" : "",
+                    at[j].min_value, at[j].max_value);
+    if (at) XFree (at);
+    GST_LOG (" image format list:");
+    fo = XvListImageFormats (src->dpy, p, &formats);
+    for (j = 0; j < formats; j++) {
+      GST_LOG ("\t-  0x%x (%4.4s) %s", fo[j].id, (char *)&fo[j].id, (fo[j].format == XvPacked) ? "packed" : "planar");
+      if (fo[j].id == (int)id) support_format = True;
+    }
+    if (fo) XFree (fo);
+    if (!support_format) continue;
+    for (; p < ai[i].base_id + ai[i].num_ports; p++) {
+      if (XvGrabPort (src->dpy, p, 0) == Success) {
+        GST_LOG ("========================================");
+        GST_DEBUG ("XvGrabPort success : %d", p);
+        GST_LOG ("========================================");
+        XvFreeAdaptorInfo (ai);
+        return p;
+      }
+    }
+  }
+  XvFreeAdaptorInfo (ai);
+  return -1;
+}
+
+static void pixmap_update (GstXVImageSrc * src, Display *dpy, tbm_bufmgr bufmgr, Pixmap pixmap,
+               int x, int y, int width, int height)
+{
+  unsigned int attachments[1];
+  int dri2_count, dri2_out_count;
+  int dri2_width, dri2_height, dri2_stride;
+  int opt;
+  tbm_bo_handle temp_virtual;
+  attachments[0] = DRI2BufferFrontLeft;
+  dri2_count = 1;
+  GST_DEBUG ("DRI2GetBuffers");
+  src->dri2_buffers = DRI2GetBuffers (dpy, pixmap, &dri2_width, &dri2_height, attachments, dri2_count, &dri2_out_count);
+  if (!src->dri2_buffers) {
+    GST_ERROR ("[Error] : fail to get buffers");
+    goto update_done;
+  }
+  if (!src->dri2_buffers[0].name) {
+    GST_ERROR ("[Error] : a handle of the dri2 buffer is null  ");
+    goto update_done;
+  }
+  GST_DEBUG ("tbm_bo_import");
+  src->bo = tbm_bo_import(bufmgr, src->dri2_buffers[0].name);
+  if (!src->bo) {
+    GST_ERROR ("[Error] : cannot import bo (key:%d)", src->dri2_buffers[0].name);
+    goto update_done;
+  }
+  dri2_stride = src->dri2_buffers[0].pitch;
+  opt = TBM_OPTION_READ|TBM_OPTION_WRITE;
+  GST_DEBUG ("tbm_bo_map");
+  temp_virtual = tbm_bo_map (src->bo, TBM_DEVICE_CPU, opt);
+  src->virtual = temp_virtual.ptr;
+  if (!src->virtual) {
+    GST_ERROR ("[Error] : fail to map ");
+    goto update_done;
+  }
+  return;
+update_done:
+  if (src->virtual) tbm_bo_unmap(src->bo);
+  src->virtual = NULL;
+  if (src->bo) tbm_bo_unref(src->bo);
+  src->bo = NULL;
+  if (src->dri2_buffers) free(src->dri2_buffers);
+  src->dri2_buffers = NULL;
+  return;
+}
+
+static Pixmap pixmap_create (GstXVImageSrc * src, Display *dpy, int width, int height)
+{
+  src->pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, DefaultDepth(dpy, DefaultScreen(dpy)));
+  src->gc = XCreateGC (dpy, src->pixmap, 0, 0);
+  XSetForeground (dpy, src->gc, 0xFFFF0000);
+  XFillRectangle (dpy, src->pixmap, src->gc, 0, 0, width, height);
+  XSync(dpy, 0);
+  XFreeGC (dpy, src->gc);
+  return src->pixmap;
+}
+
+static gboolean
+gst_xv_image_src_stop (GstBaseSrc * bsrc)
+{
+  GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
+  GST_WARNING ("stop()");
+
+  if(src->updates_thread) {
+    src->thread_return = TRUE;
+    g_cond_signal(src->pause_cond);
+    g_thread_join ( src->updates_thread);
+    src->updates_thread = NULL;
+  }
+  GST_WARNING ("stop end ");
+  return TRUE;
+}
+
+/* Interrupt a blocking request. */
+static gboolean
+gst_xv_image_src_unlock (GstBaseSrc * bsrc)
+{
+  GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
+  GST_DEBUG_OBJECT (src, "unlock()");
+  g_cond_signal(src->queue_cond);
+  return TRUE;
+}
+
+/* Interrupt interrupt. */
+static gboolean
+gst_xv_image_src_unlock_stop (GstBaseSrc * bsrc)
+{
+  GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
+  GST_DEBUG_OBJECT (src, "unlock_stop()");
+  return TRUE;
+}
+
+static gboolean
+gst_xv_image_src_get_size (GstBaseSrc * bsrc, guint64 * size)
+{
+  GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
+  GST_INFO ("Get size %x", src);
+  return FALSE;
+}
+
+static gboolean
+gst_xv_image_src_is_seekable (GstBaseSrc * bsrc)
+{
+  GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
+  GST_INFO ("Is seekable %x", src);
+  return FALSE;
+}
+
+static gboolean
+gst_xv_image_src_query (GstBaseSrc * bsrc, GstQuery * query)
+{
+  GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
+  gboolean ret;
+  GST_INFO ("src query %x", src);
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_URI:
+      ret = TRUE;
+    break;
+    default:
+      ret = FALSE;
+    break;
+  }
+
+  if (!ret)
+    ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
+
+  return ret;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  GST_DEBUG_CATEGORY_INIT (xvimagesrc_debug, "xvimagesrc", 0, "XServer display FB video capture Source");
+  return gst_element_register (plugin, "xvimagesrc", GST_RANK_PRIMARY, GST_TYPE_XV_IMAGE_SRC);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "xvimage",
+  "XServer display video src",
+  plugin_init, VERSION, "LGPL", "Samsung Electronics Co", "http://www.samsung.com")
diff --git a/xvimagesrc/src/gstxvimagesrc.h b/xvimagesrc/src/gstxvimagesrc.h
new file mode 100755 (executable)
index 0000000..25783c4
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * xvimagesrc
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hyunil Park <hyunil46.park@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_XV_IMAGE_SRC_H__
+#define __GST_XV_IMAGE_SRC_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstpushsrc.h>
+#include <glib.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/shm.h>
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/Xvproto.h>
+#include <X11/extensions/XShm.h>
+#include <X11/extensions/Xdamage.h>
+
+#include <dri2.h> //libdri2-dev, libdrm-dev
+#include <tbm_bufmgr.h>
+
+#include "xv_types.h"
+
+#define C(b,m)              (((b) >> (m)) & 0xFF)
+#define B(c,s)              ((((unsigned int)(c)) & 0xff) << (s))
+#define FOURCC(a,b,c,d)     (B(d,24) | B(c,16) | B(b,8) | B(a,0))
+#define FOURCC_RGB32        FOURCC('R','G','B','4')
+#define FOURCC_I420         FOURCC('I','4','2','0')
+#define FOURCC_SN12         FOURCC('S','N','1','2')
+#define FOURCC_NV12         FOURCC('N','V','1','2')
+#define FOURCC_ST12         FOURCC('S','T','1','2')
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_XV_IMAGE_SRC \
+  (gst_xv_image_src_get_type())
+#define GST_XV_IMAGE_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_XV_IMAGE_SRC,GstXVImageSrc))
+#define GST_XV_IMAGE_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass), \
+      GST_TYPE_XV_IMAGE_SRC,GstXVImageSrcClass))
+#define GST_IS_XV_IMAGE_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_XV_IMAGE_SRC))
+#define GST_IS_XV_IMAGE_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_XV_IMAGE_SRC))
+
+typedef struct _GstXVImageSrc GstXVImageSrc;
+typedef struct _GstXVImageSrcClass GstXVImageSrcClass;
+
+struct _GstXVImageSrc {
+  GstPushSrc element;
+  Display      *dpy;
+  int p;
+  Pixmap pixmap;
+  GC gc;
+  unsigned int width;
+  unsigned int height;
+  unsigned int framesize;
+  guint32 format_id;
+  Damage damage;
+  int damage_base;
+  unsigned int evt_base;
+  tbm_bufmgr bufmgr;
+  void *virtual;
+  tbm_bo bo;
+  DRI2Buffer* dri2_buffers;
+  guint64 running_time;
+  guint64 base_time;
+  guint64 frame_duration;
+  Atom atom_stream_off;
+  gint rate_numerator;
+  gint rate_denominator;
+  GThread *updates_thread;
+  gboolean thread_return;
+  GQueue *queue;
+  GMutex *queue_lock;
+  GCond *queue_cond;
+  GMutex *cond_lock;
+  GCond *buffer_cond;
+  gboolean pause_cond_var;
+  GCond *pause_cond;
+  GMutex *pause_cond_lock;
+  GCond *pause_resp;
+  GMutex *pause_resp_lock;
+  GMutex *buffer_cond_lock;
+  GMutex *dpy_lock;
+  gint drm_fd;
+  gboolean is_secured_mode;
+  int current_data_type;
+  int new_data_type;
+  long get_image_overtime;
+  int get_image_overtime_cnt;
+  int gemname_cnt;
+  int tz_enable;
+  long sleep_base_time;
+  long sleep_limit_time;
+  gboolean switching_to_udp;
+  guint64 initial_audio_latency;
+  guint64 display_rotate;
+
+  /* For display selection */
+  Window win;
+  Atom requestor;
+  Atom selection;
+  Atom target;
+  Atom property;
+};
+
+struct _GstXVImageSrcClass {
+  GstPushSrcClass parent_class;
+
+  /* signals */
+  void (*ui_only)      (void *data);
+  void (*video_with_ui)        (void *data);
+  void (*video_only)   (void *data);
+  void (*selection_notify)     (void *data);
+};
+
+GType gst_xv_image_src_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_XV_IMAGE_SRC_H__ */
+
diff --git a/xvimagesrc/src/xv_types.h b/xvimagesrc/src/xv_types.h
new file mode 100644 (file)
index 0000000..99fda51
--- /dev/null
@@ -0,0 +1,89 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*                                                              */
+/* File name : xv_types.h                                       */
+/* Author : Boram Park (boram1288.park@samsung.com)             */
+/* Protocol Version : 1.0.1 (Dec 16th 2009)                       */
+/* This file is for describing Xv APIs' buffer encoding method. */
+/*                                                              */
+
+#ifndef __XV_TYPE_H__
+#define __XV_TYPE_H__
+
+#define XV_DATA_HEADER 0xDEADCD01
+#define XV_DATA_VERSION        0x00010001
+
+/* Return Values */
+#define XV_OK 0
+#define XV_HEADER_ERROR -1
+#define XV_VERSION_MISMATCH -2
+
+#define XV_BUF_TYPE_DMABUF  0
+#define XV_BUF_TYPE_LEGACY  1
+
+/* Data structure for XvPutImage / XvShmPutImage */
+typedef struct
+{
+    unsigned int _header; /* for internal use only */
+    unsigned int _version; /* for internal use only */
+
+    unsigned int YBuf;
+    unsigned int CbBuf;
+    unsigned int CrBuf;
+
+    unsigned int BufType;
+} XV_DATA, * XV_DATA_PTR;
+
+static void
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+XV_INIT_DATA (XV_DATA_PTR data)
+{
+    data->_header = XV_DATA_HEADER;
+    data->_version = XV_DATA_VERSION;
+}
+
+static int
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+XV_VALIDATE_DATA (XV_DATA_PTR data)
+{
+    if (data->_header != XV_DATA_HEADER)
+        return XV_HEADER_ERROR;
+    if (data->_version != XV_DATA_VERSION)
+        return XV_VERSION_MISMATCH;
+    return XV_OK;
+}
+
+#endif
+