diff --git a/.gitignore b/.gitignore
index 10733a9..60340ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@ gst-plugins-bad-*.tar.*
 /m4
 Makefile.in
 Makefile
+TAGS
 *.gir
 *.typelib
 
diff --git a/configure.ac b/configure.ac
index fc43831..46943c0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1120,6 +1120,37 @@ AG_GST_CHECK_FEATURE(CHROMAPRINT, [chromaprint], chromaprint, [
   AC_SUBST(CHROMAPRINT_LIBS)
 ])
 
+dnl *** crystalhd ***
+translit(dnm, m, l) AM_CONDITIONAL(USE_CRYSTALHD, true)
+AG_GST_CHECK_FEATURE(CRYSTALHD, [crystalhd library], crystalhd, [
+  CRYSTALHD_CFLAGS="-I/usr/include/libcrystalhd"
+  CRYSTALHD_LIBS="-lcrystalhd"
+
+  save_CFLAGS=$CFLAGS
+  save_LIBS=$LIBS
+  CFLAGS="$CFLAGS $CRYSTALHD_CFLAGS"
+  LIBS="$LIBS $CRYSTALHD_LIBS"
+
+  AC_MSG_CHECKING([for crystalhd])
+  AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <inttypes.h>
+#include <stdlib.h>
+#include <libcrystalhd_if.h>
+]], [[
+    DtsDeviceClose(NULL);
+]])],
+  [ AC_MSG_RESULT(yes)
+    HAVE_CRYSTALHD="yes"
+    AC_SUBST(CRYSTALHD_CFLAGS)
+    AC_SUBST(CRYSTALHD_LIBS)
+  ],[AC_MSG_RESULT(no)
+     HAVE_CRYSTALHD="no"
+  ])
+
+  LIBS=$save_LIBS
+  CFLAGS=$save_CFLAGS
+])
+
 dnl *** Curl ***
 translit(dnm, m, l) AM_CONDITIONAL(USE_CURL, true)
 AG_GST_CHECK_FEATURE(CURL, [Curl plugin], curl, [
@@ -2195,6 +2226,7 @@ AM_CONDITIONAL(USE_VOAACENC, false)
 AM_CONDITIONAL(USE_APEXSINK, false)
 AM_CONDITIONAL(USE_BZ2, false)
 AM_CONDITIONAL(USE_CHROMAPRINT, false)
+AM_CONDITIONAL(USE_CRYSTALHD, false)
 AM_CONDITIONAL(USE_CURL, false)
 AM_CONDITIONAL(USE_SSH2, false)
 AM_CONDITIONAL(USE_DASH, false)
@@ -2466,6 +2498,7 @@ ext/voamrwbenc/Makefile
 ext/voaacenc/Makefile
 ext/assrender/Makefile
 ext/apexsink/Makefile
+ext/bcmdec/Makefile
 ext/bz2/Makefile
 ext/chromaprint/Makefile
 ext/curl/Makefile
diff --git a/ext/Makefile.am b/ext/Makefile.am
index c06d481..c2fafc6 100644
--- a/ext/Makefile.am
+++ b/ext/Makefile.am
@@ -28,6 +28,12 @@ else
 BZ2_DIR=
 endif
 
+if USE_CRYSTALHD
+BCMDEC_DIR=bcmdec
+else
+BCMDEC_DIR=
+endif
+
 if USE_CHROMAPRINT
 CHROMAPRINT_DIR=chromaprint
 else
@@ -383,6 +389,7 @@ SUBDIRS=\
 	$(APEXSINK_DIR) \
 	$(AUDIOFILE_DIR) \
 	$(BZ2_DIR) \
+	$(BCMDEC_DIR) \
 	$(CHROMAPRINT_DIR) \
 	$(CURL_DIR) \
 	$(DASH_DIR) \
diff --git a/ext/bcmdec/Makefile.am b/ext/bcmdec/Makefile.am
new file mode 100644
index 0000000..8ad4f3e
--- /dev/null
+++ b/ext/bcmdec/Makefile.am
@@ -0,0 +1,13 @@
+plugin_LTLIBRARIES = libgstbcmdec.la
+
+BCMDEC_CFLAGS = -D__LINUX_USER__ -DWMV_FILE_HANDLING
+
+libgstbcmdec_la_SOURCES = gstbcmdec.c decif.c parse.c
+libgstbcmdec_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_CFLAGS) \
+	$(BCMDEC_CFLAGS) $(CRYSTALHD_CFLAGS)
+libgstbcmdec_la_LIBADD = $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS) \
+	$(CRYSTALHD_LIBS)
+libgstbcmdec_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstbcmdev_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
+
+noinst_HEADERS = gstbcmdec.h decif.h parse.h
diff --git a/ext/bcmdec/decif.c b/ext/bcmdec/decif.c
new file mode 100644
index 0000000..a3c47f5
--- /dev/null
+++ b/ext/bcmdec/decif.c
@@ -0,0 +1,224 @@
+/********************************************************************
+ * Copyright(c) 2008 Broadcom Corporation.
+ *
+ *  Name: decif.cpp
+ *
+ *  Description: Device Interface API.
+ *
+ *  AU
+ *
+ *  HISTORY:
+ *
+ *******************************************************************
+ *
+ * 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.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ *******************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <getopt.h>
+#include <errno.h>
+#include <glib.h>
+#include <gst/gst.h>
+
+#include "decif.h"
+
+BC_STATUS
+decif_getcaps (BcmDecIF * decif, BC_HW_CAPS * hwCaps)
+{
+  BC_STATUS sts = BC_STS_SUCCESS;
+  if (decif != NULL)
+    sts = DtsGetCapabilities (decif->hdev, hwCaps);
+  else
+    sts = DtsGetCapabilities (NULL, hwCaps);
+  return sts;
+}
+
+BC_STATUS
+decif_open (BcmDecIF * decif)
+{
+  BC_STATUS sts = BC_STS_SUCCESS;
+  guint32 mode =
+      DTS_PLAYBACK_MODE | DTS_LOAD_FILE_PLAY_FW | DTS_SKIP_TX_CHK_CPB |
+      DTS_DFLT_RESOLUTION (vdecRESOLUTION_720p29_97);
+  sts = DtsDeviceOpen (&decif->hdev, mode);
+  if (sts != BC_STS_SUCCESS)
+    decif->hdev = NULL;
+
+  return sts;
+}
+
+BC_STATUS
+decif_close (BcmDecIF * decif)
+{
+  BC_STATUS sts = BC_STS_SUCCESS;
+  if (decif->hdev) {
+    sts = DtsDeviceClose (decif->hdev);
+    decif->hdev = NULL;
+  }
+
+  return sts;
+}
+
+BC_STATUS
+decif_prepare_play (BcmDecIF * decif)
+{
+  BC_STATUS sts = BC_STS_SUCCESS;
+  uint32_t stream_type = BC_STREAM_TYPE_ES;
+
+  sts = DtsOpenDecoder (decif->hdev, stream_type);
+  return sts;
+
+}
+
+BC_STATUS
+decif_start_play (BcmDecIF * decif)
+{
+  BC_STATUS sts = DtsStartDecoder (decif->hdev);
+
+  if (sts != BC_STS_SUCCESS)
+    return sts;
+
+  sts = DtsStartCapture (decif->hdev);
+
+  return sts;
+}
+
+BC_STATUS
+decif_pause (BcmDecIF * decif, gboolean pause)
+{
+  BC_STATUS sts;
+
+  if (pause)
+    sts = DtsPauseDecoder (decif->hdev);
+  else
+    sts = DtsResumeDecoder (decif->hdev);
+
+  return sts;
+}
+
+BC_STATUS
+decif_stop (BcmDecIF * decif)
+{
+  BC_STATUS sts = DtsStopDecoder (decif->hdev);
+
+  if (sts != BC_STS_SUCCESS)
+    return sts;
+
+  sts = DtsCloseDecoder (decif->hdev);
+
+  return sts;
+}
+
+BC_STATUS
+decif_flush_dec (BcmDecIF * decif, gint8 flush_type)
+{
+  return DtsFlushInput (decif->hdev, flush_type);
+}
+
+BC_STATUS
+decif_flush_rxbuf (BcmDecIF * decif, gboolean discard_only)
+{
+  return DtsFlushRxCapture (decif->hdev, discard_only);
+}
+
+BC_STATUS
+decif_setcolorspace (BcmDecIF * decif, BC_OUTPUT_FORMAT mode)
+{
+  return DtsSetColorSpace (decif->hdev, mode);
+}
+
+BC_STATUS
+decif_send_buffer (BcmDecIF * decif, guint8 * buffer, guint32 size,
+    GstClockTime time_stamp, guint8 flags)
+{
+  BC_STATUS sts = BC_STS_SUCCESS;
+//      guint8 odd_bytes = 0;
+//      guint8 *psend_buff = decif->aligned_buf;
+//
+//      while(((uintptr_t)psend_buff) & 0x03)
+//              psend_buff++;
+//
+//      if (((uintptr_t)buffer) % 4) odd_bytes = 4 - ((guint8)((uintptr_t)buffer % 4));
+//
+//      if (odd_bytes) {
+//              memcpy(psend_buff, buffer, odd_bytes);
+//              sts = DtsProcInput(decif->hdev, psend_buff, odd_bytes, time_stamp, flags);
+//              time_stamp = 0;
+//              if (sts != BC_STS_SUCCESS)
+//                      return sts;
+//              buffer += odd_bytes;
+//              size -= odd_bytes;
+//              if (!size)
+//                      return BC_STS_SUCCESS;
+//      }
+
+  sts = DtsProcInput (decif->hdev, buffer, size, time_stamp, flags);
+
+  return sts;
+}
+
+BC_STATUS
+decif_get_drv_status (BcmDecIF * decif, gboolean * suspended, guint32 * rll,
+    guint32 * picNumFlags)
+{
+  BC_DTS_STATUS drv_status;
+  BC_STATUS sts = DtsGetDriverStatus (decif->hdev, &drv_status);
+  if (sts == BC_STS_SUCCESS) {
+    if (drv_status.PowerStateChange)
+      *suspended = TRUE;
+    else
+      *suspended = FALSE;
+    *rll = drv_status.ReadyListCount;
+    *picNumFlags = drv_status.picNumFlags;
+  }
+
+  return sts;
+}
+
+BC_STATUS
+decif_get_eos (BcmDecIF * decif, gboolean * bEOS)
+{
+  return DtsIsEndOfStream (decif->hdev, (uint8_t *) bEOS);
+}
+
+BC_STATUS
+decif_decode_catchup (BcmDecIF * decif, gboolean catchup)
+{
+  BC_STATUS sts;
+
+  return sts = BC_STS_SUCCESS;  // Temporarily disable Catchup
+
+  if (catchup)
+    sts = DtsSetFFRate (decif->hdev, 2);
+  else
+    sts = DtsSetFFRate (decif->hdev, 1);
+
+  return sts;
+}
+
+BC_STATUS
+decif_setinputformat (BcmDecIF * decif, BC_INPUT_FORMAT bcInputFormat)
+{
+  BC_STATUS sts = BC_STS_SUCCESS;
+
+  sts = DtsSetInputFormat (decif->hdev, &bcInputFormat);
+
+  return sts;
+}
diff --git a/ext/bcmdec/decif.h b/ext/bcmdec/decif.h
new file mode 100644
index 0000000..4c504ff
--- /dev/null
+++ b/ext/bcmdec/decif.h
@@ -0,0 +1,76 @@
+/********************************************************************
+ * Copyright(c) 2008 Broadcom Corporation.
+ *
+ *  Name: decif.h
+ *
+ *  Description: Devic Interface API.
+ *
+ *  AU
+ *
+ *  HISTORY:
+ *
+ *******************************************************************
+ *
+ * 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.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ *******************************************************************/
+#ifndef __BCMDECIF_H__
+#define __BCMDECIF_H__
+
+#include "bc_dts_defs.h"
+#include "libcrystalhd_if.h"
+
+#define PROC_TIMEOUT 3000
+#define ALIGN_BUF_SIZE	(512*1024)
+
+struct _DecIf
+{
+  HANDLE hdev;
+};
+typedef struct _DecIf BcmDecIF;
+
+BC_STATUS decif_getcaps (BcmDecIF * decif, BC_HW_CAPS * hwCaps);
+
+BC_STATUS decif_open (BcmDecIF * decif);
+
+BC_STATUS decif_close (BcmDecIF * decif);
+
+BC_STATUS decif_prepare_play (BcmDecIF * decif);
+
+BC_STATUS decif_start_play (BcmDecIF * decif);
+
+BC_STATUS decif_pause (BcmDecIF * decif, gboolean pause);
+
+BC_STATUS decif_stop (BcmDecIF * decif);
+
+BC_STATUS decif_flush_dec (BcmDecIF * decif, gint8 flush_type);
+
+BC_STATUS decif_flush_rxbuf (BcmDecIF * decif, gboolean discard_only);
+
+BC_STATUS
+decif_send_buffer (BcmDecIF * decif, guint8 * buffer, guint32 size,
+    GstClockTime time_stamp, guint8 flags);
+
+BC_STATUS decif_setcolorspace (BcmDecIF * decif, BC_OUTPUT_FORMAT mode);
+
+BC_STATUS
+decif_get_drv_status (BcmDecIF * decif, gboolean * suspended, guint32 * rll,
+    guint32 * picNumFlags);
+
+BC_STATUS decif_get_eos (BcmDecIF * decif, gboolean * bEOS);
+
+BC_STATUS decif_decode_catchup (BcmDecIF * decif, gboolean catchup);
+
+BC_STATUS
+decif_setinputformat (BcmDecIF * decif, BC_INPUT_FORMAT bcInputFormat);
+
+#endif
diff --git a/ext/bcmdec/gstbcmdec.c b/ext/bcmdec/gstbcmdec.c
new file mode 100644
index 0000000..f58b595
--- /dev/null
+++ b/ext/bcmdec/gstbcmdec.c
@@ -0,0 +1,2748 @@
+/********************************************************************
+ * Copyright(c) 2008 Broadcom Corporation.
+ *
+ *  Name: gstbcmdec.c
+ *
+ *  Description: Broadcom 70012 decoder plugin
+ *
+ *  AU
+ *
+ *  HISTORY:
+ *     Updated for 1.0 by Guido Guenther <agx@sigxcpu.org>
+ *
+ *******************************************************************
+ *
+ * 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.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ *******************************************************************/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/shm.h>
+#include <pthread.h>
+#include <sys/times.h>
+#include <semaphore.h>
+#include <getopt.h>
+#include <errno.h>
+#include <time.h>
+#include <glib.h>
+#include <gst/base/gstadapter.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideopool.h>
+
+#include <gst/gst.h>
+
+#include "decif.h"
+#include "parse.h"
+#include "gstbcmdec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_bcm_dec_debug);
+#define GST_CAT_DEFAULT gst_bcm_dec_debug
+
+//#define YV12__
+
+//#define FILE_DUMP__ 1
+
+static GstFlowReturn
+bcmdec_send_buff_detect_error (GstBcmDec * bcmdec, GstBuffer * buf,
+    guint8 * pbuffer, guint32 size,
+    guint32 offset, GstClockTime tCurrent, guint8 flags)
+{
+  BC_STATUS sts = BC_STS_SUCCESS;
+  GstMapInfo info;
+
+  GST_DEBUG_OBJECT (bcmdec, "Attempting to Send Buffer");
+
+  sts = decif_send_buffer (&bcmdec->decif, pbuffer, size, tCurrent, flags);
+
+  if (sts != BC_STS_SUCCESS) {
+    gst_buffer_map (buf, &info, GST_MAP_READ);
+    GST_ERROR_OBJECT (bcmdec, "proc input failed sts = %d", sts);
+    GST_ERROR_OBJECT (bcmdec, "Chain: timeStamp = %llu size = %d data = %p",
+        GST_BUFFER_DTS (buf), info.size, info.data);
+    gst_buffer_unmap (buf, &info);
+    return GST_FLOW_ERROR;
+  }
+
+  return GST_FLOW_OK;
+}
+
+/* bcmdec signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_SILENT
+};
+
+
+static GLB_INST_STS *g_inst_sts = NULL;
+
+/*
+ * the capabilities of the inputs and outputs.
+ *
+ * describe the real formats here.
+ */
+GstStaticPadTemplate sink_factory_bcm70015 =
+    GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/mpeg, " "mpegversion = (int) {2, 4},"
+        "systemstream =(boolean) false; " "video/x-h264;" "video/x-vc1;"
+        "video/x-wmv, " "wmvversion = (int) {3};" "video/x-msmpeg, "
+        "msmpegversion = (int) {43};" "video/x-divx, "
+        "divxversion = (int) {3, 4, 5};" "video/x-xvid;"));
+
+GstStaticPadTemplate sink_factory_bcm70012 =
+    GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/mpeg, " "mpegversion = (int) {2},"
+        "systemstream =(boolean) false; " "video/x-h264;" "video/x-vc1;"
+        "video/x-wmv, " "wmvversion = (int) {3};"));
+
+#ifdef YV12__
+static GstStaticPadTemplate src_factory =
+GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/x-raw, " "format = (string) { YV12 }, "
+        "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ], "
+        "framerate = (fraction) [ 0/1, 2147483647/1 ]"));
+#define BUF_MULT (12 / 8)
+#define BUF_MODE MODE420
+#else
+static GstStaticPadTemplate src_factory =
+    GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/x-raw, " "format = (string) { YUY2 } , "
+        "framerate = (fraction) [0,MAX], " "width = (int) [1,MAX], "
+        "height = (int) [1,MAX]; " "video/x-raw, "
+        "format = (string) { UYVY } , " "framerate = (fraction) [0,MAX], "
+        "width = (int) [1,MAX], " "height = (int) [1,MAX]; "));
+#define BUF_MULT (16 / 8)
+#define BUF_MODE MODE422_YUY2
+#endif
+
+G_DEFINE_TYPE (GstBcmDec, gst_bcm_dec, GST_TYPE_ELEMENT);
+
+/* GObject vmethod implementations */
+
+static void
+gst_bcm_dec_base_init (gpointer gclass)
+{
+  BC_HW_CAPS hwCaps;
+  GstElementClass *element_class;
+
+  GST_DEBUG_OBJECT (gclass, "gst_bcm_dec_base_init");
+  element_class = GST_ELEMENT_CLASS (gclass);
+
+  hwCaps.DecCaps = 0;
+  decif_getcaps (NULL, &hwCaps);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_factory));
+  if (hwCaps.DecCaps & BC_DEC_FLAGS_M4P2) {
+    GST_DEBUG_OBJECT (gclass, "Found M4P2 support");
+    gst_element_class_add_pad_template (element_class,
+        gst_static_pad_template_get (&sink_factory_bcm70015));
+  } else
+    gst_element_class_add_pad_template (element_class,
+        gst_static_pad_template_get (&sink_factory_bcm70012));
+  gst_element_class_set_metadata (element_class, "Codec/Decoder/Video",
+      "Generic Video Decoder",
+      "Decodes various Video Formats using CrystalHD Decoders",
+      "Broadcom Corp.");
+}
+
+/* initialize the bcmdec's class */
+static void
+gst_bcm_dec_class_init (GstBcmDecClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  GST_DEBUG_OBJECT (klass, "gst_bcm_dec_class_init");
+
+  gst_bcm_dec_base_init (klass);
+
+  gstelement_class->change_state = gst_bcm_dec_change_state;
+
+  gobject_class->set_property = gst_bcm_dec_set_property;
+  gobject_class->get_property = gst_bcm_dec_get_property;
+  gobject_class->finalize = gst_bcm_dec_finalize;
+
+  g_object_class_install_property (gobject_class, PROP_SILENT,
+      g_param_spec_boolean ("silent", "Silent",
+          "Produce verbose output ?", FALSE, (GParamFlags) G_PARAM_READWRITE));
+}
+
+/*
+ * initialize the new element
+ * instantiate pads and add them to element
+ * set pad calback functions
+ * initialize instance structure
+ */
+static void
+gst_bcm_dec_init (GstBcmDec * bcmdec)
+{
+  pid_t pid;
+  BC_STATUS sts = BC_STS_SUCCESS;
+  int shmid = 0;
+  BC_HW_CAPS hwCaps;
+
+  GST_DEBUG_OBJECT (bcmdec, "gst_bcm_dec_init");
+
+  bcmdec_reset (bcmdec);
+
+  hwCaps.DecCaps = 0;
+  sts = decif_getcaps (&bcmdec->decif, &hwCaps);
+  if (hwCaps.DecCaps & BC_DEC_FLAGS_M4P2) {
+    bcmdec->sinkpad =
+        gst_pad_new_from_static_template (&sink_factory_bcm70015, "sink");
+  } else
+    bcmdec->sinkpad =
+        gst_pad_new_from_static_template (&sink_factory_bcm70012, "sink");
+
+  gst_pad_set_event_function (bcmdec->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_bcm_dec_sink_event));
+
+  gst_pad_set_chain_function (bcmdec->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_bcm_dec_chain));
+
+  bcmdec->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
+
+  gst_pad_set_event_function (bcmdec->srcpad,
+      GST_DEBUG_FUNCPTR (gst_bcm_dec_src_event));
+
+  gst_pad_use_fixed_caps (bcmdec->srcpad);
+  bcmdec_negotiate_format (bcmdec);
+
+  gst_element_add_pad (GST_ELEMENT (bcmdec), bcmdec->sinkpad);
+  gst_element_add_pad (GST_ELEMENT (bcmdec), bcmdec->srcpad);
+  bcmdec->silent = FALSE;
+  pid = getpid ();
+  GST_DEBUG_OBJECT (bcmdec, "gst_bcm_dec_init _-- PID = %x", pid);
+
+  sts = bcmdec_create_shmem (bcmdec, &shmid);
+
+  GST_DEBUG_OBJECT (bcmdec, "bcmdec_create_shmem _-- Sts = %x", sts);
+}
+
+/* plugin close function*/
+static void
+gst_bcm_dec_finalize (GObject * object)
+{
+  GstBcmDec *bcmdec = GST_BCM_DEC (object);
+
+  bcmdec_del_shmem (bcmdec);
+  /*gst_bcm_dec_cleanup(bcmdec); */
+  GST_DEBUG_OBJECT (bcmdec, "gst_bcm_dec_finalize");
+  G_OBJECT_CLASS (gst_bcm_dec_parent_class)->finalize (object);
+}
+
+static void
+gst_bcm_dec_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstBcmDec *bcmdec = GST_BCM_DEC (object);
+
+  switch (prop_id) {
+    case PROP_SILENT:
+      bcmdec->silent = g_value_get_boolean (value);
+      GST_DEBUG_OBJECT (bcmdec, "gst_bcm_dec_set_property PROP_SILENT");
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+
+  if (!bcmdec->silent)
+    GST_DEBUG_OBJECT (bcmdec, "gst_bcm_dec_set_property");
+}
+
+static void
+gst_bcm_dec_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstBcmDec *bcmdec = GST_BCM_DEC (object);
+
+  switch (prop_id) {
+    case PROP_SILENT:
+      g_value_set_boolean (value, bcmdec->silent);
+      GST_DEBUG_OBJECT (bcmdec, "gst_bcm_dec_get_property PROP_SILENT");
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+
+  if (!bcmdec->silent)
+    GST_DEBUG_OBJECT (bcmdec, "gst_bcm_dec_get_property");
+}
+
+/* GstElement vmethod implementations */
+static gboolean
+gst_bcm_dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+  const GstSegment *newsegment;
+  GstBcmDec *bcmdec;
+  GstCaps *caps;
+  BC_STATUS sts = BC_STS_SUCCESS;
+  gboolean result = TRUE;
+
+  bcmdec = GST_BCM_DEC (gst_pad_get_parent (pad));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CAPS:
+      gst_event_parse_caps (event, &caps);
+      result = gst_bcm_dec_sink_set_caps (pad, caps);
+      break;
+
+    case GST_EVENT_SEGMENT:
+      gst_event_parse_segment (event, &newsegment);
+
+      bcmdec->base_clock_time = newsegment->start;
+      bcmdec->cur_stream_time = 0;
+
+      if (!bcmdec->silent)
+        GST_DEBUG_OBJECT (bcmdec, "new segment");
+
+      bcmdec->codec_params.inside_buffer = TRUE;
+      bcmdec->codec_params.consumed_offset = 0;
+      bcmdec->codec_params.strtcode_offset = 0;
+      bcmdec->codec_params.nal_sz = 0;
+      bcmdec->insert_pps = TRUE;
+      bcmdec->base_time = 0;
+
+      bcmdec->spes_frame_cnt = 0;
+      bcmdec->catchup_on = FALSE;
+      bcmdec->last_output_spes_time = 0;
+      bcmdec->last_spes_time = 0;
+
+      result = gst_pad_push_event (bcmdec->srcpad, event);
+      break;
+
+    case GST_EVENT_FLUSH_START:
+      GST_DEBUG_OBJECT (bcmdec, "Flush Start");
+
+#if 0
+      pthread_mutex_lock (&bcmdec->fn_lock);
+      if (!g_inst_sts->waiting) /*in case of playback process waiting */
+        bcmdec_process_flush_start (bcmdec);
+      pthread_mutex_unlock (&bcmdec->fn_lock);
+#endif
+      bcmdec_process_flush_start (bcmdec);
+      result = gst_pad_push_event (bcmdec->srcpad, event);
+      break;
+
+    case GST_EVENT_FLUSH_STOP:
+      if (!bcmdec->silent)
+        GST_DEBUG_OBJECT (bcmdec, "Flush Stop");
+      //if (!g_inst_sts->waiting)
+      //      bcmdec_process_flush_stop(bcmdec);
+      bcmdec_process_flush_stop (bcmdec);
+      result = gst_pad_push_event (bcmdec->srcpad, event);
+      break;
+
+    case GST_EVENT_EOS:
+      if (!bcmdec->silent)
+        GST_DEBUG_OBJECT (bcmdec, "EOS on sink pad");
+      sts = decif_flush_dec (&bcmdec->decif, 0);
+      GST_DEBUG_OBJECT (bcmdec, "dec_flush ret = %d", sts);
+      bcmdec->ev_eos = event;
+      gst_event_ref (bcmdec->ev_eos);
+      break;
+
+    default:
+      result = gst_pad_push_event (bcmdec->srcpad, event);
+      GST_DEBUG_OBJECT (bcmdec, "unhandled event on sink pad");
+      break;
+  }
+
+  gst_object_unref (bcmdec);
+  if (!bcmdec->silent)
+    GST_DEBUG_OBJECT (bcmdec, "gst_bcm_dec_sink_event %u",
+        GST_EVENT_TYPE (event));
+  return result;
+}
+
+/* this function handles the link with other elements */
+static gboolean
+gst_bcm_dec_sink_set_caps (GstPad * pad, GstCaps * caps)
+{
+  GstBcmDec *bcmdec;
+  GstStructure *structure;
+  GstMapInfo info;
+  GstCaps *intersection;
+  const gchar *mime;
+  guint num = 0;
+  guint den = 0;
+  const GValue *g_value;
+  int version = 0;
+  GstBuffer *buffer = NULL;
+  guint index;
+
+  bcmdec = GST_BCM_DEC (gst_pad_get_parent (pad));
+  GST_DEBUG_OBJECT (pad, "setcaps called");
+
+  intersection = gst_caps_intersect (gst_pad_get_pad_template_caps (pad), caps);
+  GST_DEBUG_OBJECT (bcmdec, "Intersection return %" GST_PTR_FORMAT,
+      intersection);
+  if (gst_caps_is_empty (intersection)) {
+    GST_ERROR_OBJECT (bcmdec, "setscaps:caps empty");
+    gst_object_unref (bcmdec);
+    return FALSE;
+  }
+  gst_caps_unref (intersection);
+  structure = gst_caps_get_structure (caps, 0);
+  mime = gst_structure_get_name (structure);
+  if (!strcmp ("video/x-h264", mime)) {
+    bcmdec->input_format = BC_MSUBTYPE_AVC1;    // GStreamer uses the bit-stream format so have to add start codes
+    // We might override this later down below if the codec_data indicates otherwise
+    // So don't print codec type yet GST_DEBUG_OBJECT(bcmdec, "InFmt H.264");
+  } else if (!strcmp ("video/mpeg", mime)) {
+    gst_structure_get_int (structure, "mpegversion", &version);
+    if (version == 2) {
+      bcmdec->input_format = BC_MSUBTYPE_MPEG2VIDEO;
+      GST_DEBUG_OBJECT (bcmdec, "InFmt MPEG2");
+    } else if (version == 4) {
+      bcmdec->input_format = BC_MSUBTYPE_DIVX;
+      GST_DEBUG_OBJECT (bcmdec, "InFmt MPEG4");
+    } else {
+      gst_object_unref (bcmdec);
+      return FALSE;
+    }
+  } else if (!strcmp ("video/x-vc1", mime)) {
+    bcmdec->input_format = BC_MSUBTYPE_VC1;
+    GST_DEBUG_OBJECT (bcmdec, "InFmt VC1");
+  } else if (!strcmp ("video/x-divx", mime)) {
+    gst_structure_get_int (structure, "divxversion", &version);
+    if (version == 3) {
+      bcmdec->input_format = BC_MSUBTYPE_DIVX311;
+      GST_DEBUG_OBJECT (bcmdec, "InFmt DIVX3");
+    } else {
+      bcmdec->input_format = BC_MSUBTYPE_DIVX;
+      GST_DEBUG_OBJECT (bcmdec, "InFmt DIVX%d", version);
+    }
+  } else if (!strcmp ("video/x-xvid", mime)) {
+    bcmdec->input_format = BC_MSUBTYPE_DIVX;
+    GST_DEBUG_OBJECT (bcmdec, "InFmt XVID");
+  } else if (!strcmp ("video/x-msmpeg", mime)) {
+    bcmdec->input_format = BC_MSUBTYPE_DIVX311;
+    GST_DEBUG_OBJECT (bcmdec, "InFmt MPMPEGv43");
+  } else if (!strcmp ("video/x-wmv", mime)) {
+    gst_structure_get_int (structure, "wmvversion", &version);
+    if (version == 3) {
+      bcmdec->input_format = BC_MSUBTYPE_WMV3;
+      GST_DEBUG_OBJECT (bcmdec, "InFmt WMV9");
+    } else {
+      gst_object_unref (bcmdec);
+      return FALSE;
+    }
+  } else {
+    GST_DEBUG_OBJECT (bcmdec, "unknown mime %s", mime);
+    gst_object_unref (bcmdec);
+    return FALSE;
+  }
+
+  g_value = gst_structure_get_value (structure, "framerate");
+  if (g_value != NULL) {
+    num = gst_value_get_fraction_numerator (g_value);
+    den = gst_value_get_fraction_denominator (g_value);
+
+    bcmdec->input_framerate = (double) num / den;
+    GST_LOG_OBJECT (bcmdec, "demux frame rate = %f ", bcmdec->input_framerate);
+  } else {
+    GST_DEBUG_OBJECT (bcmdec, "no demux framerate_value");
+  }
+
+  g_value = gst_structure_get_value (structure, "pixel-aspect-ratio");
+  if (g_value) {
+    bcmdec->input_par_x = gst_value_get_fraction_numerator (g_value);
+    bcmdec->input_par_y = gst_value_get_fraction_denominator (g_value);
+    GST_DEBUG_OBJECT (bcmdec, "sink caps have pixel-aspect-ratio of %d:%d",
+        bcmdec->input_par_x, bcmdec->input_par_y);
+    if (bcmdec->input_par_x > 5 * bcmdec->input_par_y) {
+      bcmdec->input_par_x = 1;
+      bcmdec->input_par_y = 1;
+      GST_DEBUG_OBJECT (bcmdec, "demux par reset");
+    }
+
+  } else {
+    GST_DEBUG_OBJECT (bcmdec, "no par from demux");
+  }
+
+  gst_structure_get_int (structure, "width", &bcmdec->frame_width);
+  gst_structure_get_int (structure, "height", &bcmdec->frame_height);
+
+  // Check Codec Data for various codecs
+  // Determine if this is bitstream video (AVC1 or no start codes) or Byte stream video (H264)
+  // Determine if this is VC-1 AP or SP/MP for VC-1
+  if ((g_value = gst_structure_get_value (structure, "codec_data"))) {
+    if (G_VALUE_TYPE (g_value) == GST_TYPE_BUFFER) {
+      if (!strcmp ("video/x-h264", mime)) {
+        GST_DEBUG_OBJECT (bcmdec, "Don't have start codes'");
+        bcmdec->input_format = BC_MSUBTYPE_AVC1;
+        GST_DEBUG_OBJECT (bcmdec, "InFmt H.264 (AVC1)");
+
+        buffer = gst_value_get_buffer (g_value);
+        if (!gst_buffer_map (buffer, &info, GST_MAP_READ))
+          goto map_error;
+        GST_DEBUG_OBJECT (bcmdec, "codec_data size = %d", info.size);
+
+        /* parse the avcC data */
+        if (info.size < 7) {
+          GST_ERROR_OBJECT (bcmdec, "avcC size %u < 7", info.size);
+          goto out;
+        }
+        /* parse the version, this must be 1 */
+        if (info.data[0] != 1) {
+          GST_ERROR_OBJECT (bcmdec, "wrong avcC version");
+          goto out;
+        }
+
+        if (bcmdec->codec_params.sps_pps_buf == NULL)
+          bcmdec->codec_params.sps_pps_buf = (guint8 *) malloc (info.size * 2);
+        if (bcmdec_insert_sps_pps (bcmdec, &info) != BC_STS_SUCCESS) {
+          bcmdec->codec_params.pps_size = 0;
+        }
+      } else if (!strcmp ("video/x-wmv", mime)) {
+        buffer = gst_value_get_buffer (g_value);
+        if (!gst_buffer_map (buffer, &info, GST_MAP_READ))
+          goto map_error;
+
+        GST_DEBUG_OBJECT (bcmdec, "codec_data size = %d", info.size);
+        if (info.size == 4) {
+          // Simple or Main Profile
+          bcmdec->input_format = BC_MSUBTYPE_WMV3;
+          GST_DEBUG_OBJECT (bcmdec, "InFmt VC-1 (SP/MP)");
+          if (bcmdec->codec_params.sps_pps_buf == NULL)
+            bcmdec->codec_params.sps_pps_buf = (guint8 *) malloc (4);
+          memcpy (bcmdec->codec_params.sps_pps_buf, info.data, 4);
+          bcmdec->codec_params.pps_size = 4;
+        } else {
+          bcmdec->input_format = BC_MSUBTYPE_VC1;
+          GST_DEBUG_OBJECT (bcmdec, "InFmt VC-1 (AP)");
+          for (index = 0; index < info.size; index++) {
+            info.data += index;
+            if (((info.size - index) >= 4) && (*info.data == 0x00)
+                && (*(info.data + 1) == 0x00) && (*(info.data + 2) == 0x01)
+                && (*(info.data + 3) == 0x0f)) {
+              GST_DEBUG_OBJECT (bcmdec,
+                  "VC1 Sequence Header Found for Adv Profile");
+
+              if ((info.size - index + 1) > MAX_ADV_PROF_SEQ_HDR_SZ)
+                bcmdec->codec_params.pps_size = MAX_ADV_PROF_SEQ_HDR_SZ;
+              else
+                bcmdec->codec_params.pps_size = info.size - index + 1;
+              memcpy (bcmdec->codec_params.sps_pps_buf, info.data,
+                  bcmdec->codec_params.pps_size);
+              break;
+            }
+          }
+        }
+      }
+    }
+  } else {
+    if (!strcmp ("video/x-h264", mime)) {
+      GST_DEBUG_OBJECT (bcmdec, "Have start codes'");
+      bcmdec->input_format = BC_MSUBTYPE_H264;
+      GST_DEBUG_OBJECT (bcmdec, "InFmt H.264 (H264)");;
+      bcmdec->codec_params.nal_size_bytes = 4;  // 4 sync bytes used
+    } else {
+      // No Codec data. So try with FourCC for VC1/WMV9
+      if (!strcmp ("video/x-wmv", mime)) {
+        if (gst_structure_has_field (structure, "format")) {
+          const char *fourcc = gst_structure_get_string (structure, "format");
+
+          if (!g_strcmp0 (fourcc, "WVC1") || !g_strcmp0 (fourcc, "WMVA")) {
+            bcmdec->input_format = BC_MSUBTYPE_VC1;
+            GST_DEBUG_OBJECT (bcmdec, "InFmt VC-1 (AP)");
+          } else {
+            GST_DEBUG_OBJECT (bcmdec,
+                "no codec_data. Don't know how to handle");
+            goto out;
+          }
+        }
+      } else if (bcmdec->input_format == BC_MSUBTYPE_MPEG2VIDEO) {
+        // For MPEG-2 don't need any additional codec_data is most cases
+        GST_DEBUG_OBJECT (bcmdec,
+            "no codec_data for MPEG-2. Trying to decode anyway");
+      } else if (bcmdec->input_format == BC_MSUBTYPE_DIVX) {
+        // For DIVX don't need any additional codec_data is most cases
+        GST_DEBUG_OBJECT (bcmdec,
+            "no codec_data for MPEG-4. Trying to decode anyway");
+      } else {
+        GST_DEBUG_OBJECT (bcmdec, "no codec_data. Don't know how to handle");
+        goto out;
+      }
+    }
+  }
+
+  if (bcmdec->play_pending) {
+    bcmdec->play_pending = FALSE;
+    bcmdec_process_play (bcmdec);
+  }
+
+  gst_buffer_unmap (buffer, &info);
+  gst_object_unref (bcmdec);
+
+  return TRUE;
+
+  /* ERRORS */
+out:
+  if (buffer)
+    gst_buffer_unmap (buffer, &info);
+map_error:
+  gst_object_unref (bcmdec);
+  return FALSE;
+}
+
+/*
+ * chain function
+ * this function does the actual processing
+ */
+static GstFlowReturn
+gst_bcm_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
+{
+  GstBcmDec *bcmdec;
+  GstMapInfo info;
+  guint32 offset = 0;
+  GstClockTime tCurrent = 0;
+  guint8 *pbuffer;
+  guint32 size = 0;
+  GstFlowReturn ret;
+
+#ifdef FILE_DUMP__
+  guint32 bytes_written = 0;
+#endif
+  bcmdec = GST_BCM_DEC (GST_OBJECT_PARENT (pad));
+
+#ifdef FILE_DUMP__
+  if (bcmdec->fhnd == NULL)
+    bcmdec->fhnd = fopen ("dump2.264", "a+");
+#endif
+
+  if (bcmdec->flushing) {
+    GST_DEBUG_OBJECT (bcmdec, "input while flushing");
+    ret = GST_FLOW_OK;
+    goto out;
+  }
+
+  if (GST_CLOCK_TIME_NONE != GST_BUFFER_TIMESTAMP (buf)) {
+    if (bcmdec->base_time == 0) {
+      bcmdec->base_time = GST_BUFFER_TIMESTAMP (buf);
+      GST_DEBUG_OBJECT (bcmdec, "base time is set to %llu",
+          bcmdec->base_time / 1000000);
+    }
+    tCurrent = GST_BUFFER_TIMESTAMP (buf);
+  }
+
+  if (bcmdec->play_pending) {
+    bcmdec->play_pending = FALSE;
+    bcmdec_process_play (bcmdec);
+  } else if (!bcmdec->streaming) {
+    GST_DEBUG_OBJECT (bcmdec, "input while streaming is false");
+    ret = GST_FLOW_FLUSHING;
+    goto out;
+  }
+
+  if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
+    ret = GST_FLOW_ERROR;
+    goto out;
+  }
+  pbuffer = info.data;
+  size = info.size;
+
+  /* FIXME: better send mapinfo? */
+  if (GST_FLOW_OK != bcmdec_send_buff_detect_error (bcmdec, buf, pbuffer, size,
+          offset, tCurrent, bcmdec->proc_in_flags)) {
+    ret = GST_FLOW_ERROR;
+    goto unmapout;
+  }
+#ifdef FILE_DUMP__
+  bytes_written =
+      fwrite (GST_BUFFER_DATA (buf), sizeof (unsigned char),
+      GST_BUFFER_SIZE (buf), bcmdec->fhnd);
+#endif
+
+  ret = GST_FLOW_OK;
+
+unmapout:
+  gst_buffer_unmap (buf, &info);
+out:
+  gst_buffer_unref (buf);
+  return ret;
+}
+
+static gboolean
+gst_bcm_dec_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+  gboolean result;
+  GstBcmDec *bcmdec;
+
+  bcmdec = GST_BCM_DEC (GST_OBJECT_PARENT (pad));
+
+  result = gst_pad_push_event (bcmdec->sinkpad, event);
+
+  return result;
+}
+
+static gboolean
+bcmdec_negotiate_format (GstBcmDec * bcmdec)
+{
+  GstCaps *caps;
+  gboolean result;
+  guint num = (guint) (bcmdec->output_params.framerate * 1000);
+  guint den = 1000;
+  GstStructure *s1;
+  const GValue *framerate_value;
+  GstVideoFormat vidFmt;
+  GstVideoInfo info;
+
+#ifdef YV12__
+  vidFmt = GST_VIDEO_FORMAT_YV12;
+#else
+  vidFmt = GST_VIDEO_FORMAT_YUY2;
+#endif
+  GST_DEBUG_OBJECT (bcmdec, "framerate = %f", bcmdec->output_params.framerate);
+
+  gst_video_info_init (&info);
+  gst_video_info_set_format (&info,
+      vidFmt, bcmdec->output_params.width, bcmdec->output_params.height);
+  info.fps_n = num;
+  info.fps_d = den;
+  info.par_n = bcmdec->output_params.aspectratio_x;
+  info.par_d = bcmdec->output_params.aspectratio_y;
+  info.interlace_mode = bcmdec->interlace ?
+      GST_VIDEO_INTERLACE_MODE_INTERLEAVED :
+      GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
+  caps = gst_video_info_to_caps (&info);
+  result = gst_pad_set_caps (bcmdec->srcpad, caps);
+  GST_DEBUG_OBJECT (bcmdec, "gst_bcm_dec_negotiate_format %d", result);
+
+  if (bcmdec->output_params.clr_space == MODE422_YUY2) {
+    bcmdec->output_params.y_size =
+        bcmdec->output_params.width * bcmdec->output_params.height * BUF_MULT;
+    if (bcmdec->interlace) {
+      GST_DEBUG_OBJECT (bcmdec, "bcmdec_negotiate_format Interlaced");
+      bcmdec->output_params.y_size /= 2;
+    }
+    bcmdec->output_params.uv_size = 0;
+    GST_DEBUG_OBJECT (bcmdec, "YUY2 set on caps");
+  } else if (bcmdec->output_params.clr_space == MODE420) {
+    bcmdec->output_params.y_size =
+        bcmdec->output_params.width * bcmdec->output_params.height;
+    bcmdec->output_params.uv_size =
+        bcmdec->output_params.width * bcmdec->output_params.height / 2;
+#ifdef YV12__
+    if (bcmdec->interlace) {
+      GST_DEBUG_OBJECT (bcmdec, "bcmdec_negotiate_format Interlaced");
+      bcmdec->output_params.y_size =
+          bcmdec->output_params.width * bcmdec->output_params.height / 2;
+      bcmdec->output_params.uv_size = bcmdec->output_params.y_size / 2;
+    }
+#endif
+    GST_DEBUG_OBJECT (bcmdec, "420 set on caps");
+  }
+
+  s1 = gst_caps_get_structure (caps, 0);
+
+  framerate_value = gst_structure_get_value (s1, "framerate");
+  if (framerate_value != NULL) {
+    num = gst_value_get_fraction_numerator (framerate_value);
+    den = gst_value_get_fraction_denominator (framerate_value);
+    GST_DEBUG_OBJECT (bcmdec, "framerate = %f rate_num %d rate_den %d",
+        bcmdec->output_params.framerate, num, den);
+  } else {
+    GST_DEBUG_OBJECT (bcmdec, "failed to get framerate_value");
+  }
+
+  framerate_value = gst_structure_get_value (s1, "pixel-aspect-ratio");
+  if (framerate_value) {
+    num = gst_value_get_fraction_numerator (framerate_value);
+    den = gst_value_get_fraction_denominator (framerate_value);
+    GST_DEBUG_OBJECT (bcmdec, "pixel-aspect-ratio_x = %d y %d ", num, den);
+  } else {
+    GST_DEBUG_OBJECT (bcmdec, "failed to get par");
+  }
+
+  gst_caps_unref (caps);
+
+  return result;
+}
+
+static gboolean
+bcmdec_process_play (GstBcmDec * bcmdec)
+{
+  BC_STATUS sts = BC_STS_SUCCESS;
+
+  BC_INPUT_FORMAT bcInputFormat;
+
+  GST_DEBUG_OBJECT (bcmdec, "Starting Process Play");
+
+  bcInputFormat.OptFlags = 0;   // NAREN - FIXME - Should we enable BD mode and max frame rate mode for LINK?
+  bcInputFormat.FGTEnable = FALSE;
+  bcInputFormat.MetaDataEnable = FALSE;
+  bcInputFormat.Progressive = !(bcmdec->interlace);
+  bcInputFormat.mSubtype = bcmdec->input_format;
+
+  //Use Demux Image Size for VC-1 Simple/Main and for DIVX311
+  if (bcInputFormat.mSubtype == BC_MSUBTYPE_WMV3
+      || bcInputFormat.mSubtype == BC_MSUBTYPE_DIVX311) {
+    //VC-1 Simple/Main
+    bcInputFormat.width = bcmdec->frame_width;
+    bcInputFormat.height = bcmdec->frame_height;
+  } else {
+    bcInputFormat.width = bcmdec->output_params.width;
+    bcInputFormat.height = bcmdec->output_params.height;
+  }
+
+  bcInputFormat.startCodeSz = bcmdec->codec_params.nal_size_bytes;
+  bcInputFormat.pMetaData = bcmdec->codec_params.sps_pps_buf;
+  bcInputFormat.metaDataSz = bcmdec->codec_params.pps_size;
+  bcInputFormat.OptFlags = 0x80000000 | vdecFrameRate23_97;
+
+  // ENABLE the Following lines if HW Scaling is desired
+  bcInputFormat.bEnableScaling = FALSE;
+//      bcInputFormat.ScalingParams.sWidth = 800;
+
+  sts = decif_setinputformat (&bcmdec->decif, bcInputFormat);
+  if (sts == BC_STS_SUCCESS) {
+    GST_DEBUG_OBJECT (bcmdec, "set input format success");
+  } else {
+    GST_ERROR_OBJECT (bcmdec, "set input format failed");
+    bcmdec->streaming = FALSE;
+    return FALSE;
+  }
+
+  sts = decif_prepare_play (&bcmdec->decif);
+  if (sts == BC_STS_SUCCESS) {
+    GST_DEBUG_OBJECT (bcmdec, "prepare play success");
+  } else {
+    GST_ERROR_OBJECT (bcmdec, "prepare play failed");
+    bcmdec->streaming = FALSE;
+    return FALSE;
+  }
+
+  GST_DEBUG_OBJECT (bcmdec, "Setting color space %d", BUF_MODE);
+
+  decif_setcolorspace (&bcmdec->decif, BUF_MODE);
+
+  sts = decif_start_play (&bcmdec->decif);
+  if (sts == BC_STS_SUCCESS) {
+    GST_DEBUG_OBJECT (bcmdec, "start play success");
+    bcmdec->streaming = TRUE;
+  } else {
+    GST_ERROR_OBJECT (bcmdec, "start play failed");
+    bcmdec->streaming = FALSE;
+    return FALSE;
+  }
+
+  if (sem_post (&bcmdec->play_event) == -1)
+    GST_ERROR_OBJECT (bcmdec, "sem_post failed");
+
+  if (sem_post (&bcmdec->push_start_event) == -1)
+    GST_ERROR_OBJECT (bcmdec, "push_start post failed");
+
+  return TRUE;
+}
+
+static GstStateChangeReturn
+gst_bcm_dec_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
+  GstBcmDec *bcmdec = GST_BCM_DEC (element);
+  BC_STATUS sts = BC_STS_SUCCESS;
+  int ret = 0;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      GST_DEBUG_OBJECT (bcmdec, "State change from NULL_TO_READY");
+      if (bcmdec_mul_inst_cor (bcmdec)) {
+        sts = decif_open (&bcmdec->decif);
+        if (sts == BC_STS_SUCCESS) {
+          GST_DEBUG_OBJECT (bcmdec, "dev open success");
+          parse_init (&bcmdec->parse);
+        } else {
+          GST_ERROR_OBJECT (bcmdec, "dev open failed %d", sts);
+          GST_ERROR_OBJECT (bcmdec,
+              "dev open failed...ret GST_STATE_CHANGE_FAILURE");
+          return GST_STATE_CHANGE_FAILURE;
+        }
+      } else {
+        GST_ERROR_OBJECT (bcmdec,
+            "dev open failed...ret GST_STATE_CHANGE_FAILURE");
+        return GST_STATE_CHANGE_FAILURE;
+      }
+
+      break;
+
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      if (!bcmdec_start_recv_thread (bcmdec)) {
+        GST_ERROR_OBJECT (bcmdec, "GST_STATE_CHANGE_NULL_TO_READY -failed");
+        return GST_STATE_CHANGE_FAILURE;
+      }
+      if (!bcmdec_start_push_thread (bcmdec)) {
+        GST_ERROR_OBJECT (bcmdec, "GST_STATE_CHANGE_READY_TO_THREAD -failed");
+        return GST_STATE_CHANGE_FAILURE;
+      }
+      if (!bcmdec_start_get_rbuf_thread (bcmdec)) {
+        GST_ERROR_OBJECT (bcmdec, "GST_STATE_CHANGE_THREAD_TO_RBUF -failed");
+        return GST_STATE_CHANGE_FAILURE;
+      }
+
+      bcmdec->play_pending = TRUE;
+      GST_DEBUG_OBJECT (bcmdec, "GST_STATE_CHANGE_READY_TO_PAUSED");
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      GST_DEBUG_OBJECT (bcmdec, "GST_STATE_CHANGE_PAUSED_TO_PLAYING");
+      bcmdec->gst_clock = gst_element_get_clock (element);
+      if (bcmdec->gst_clock) {
+#if 0
+        GstClockTime clock_time, base_clock_time;
+        printf ("clock available %p\n", bcmdec->gst_clock);
+        base_clock_time = gst_element_get_base_time (element);
+        printf ("base clock time %lld\n", base_clock_time);
+        clock_time = gst_clock_get_time (bcmdec->gst_clock);
+        printf (" clock time %lld\n", clock_time);
+#endif
+      }
+      break;
+
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      GST_DEBUG_OBJECT (bcmdec, "GST_STATE_CHANGE_PAUSED_TO_READY");
+      bcmdec->streaming = FALSE;
+      GST_DEBUG_OBJECT (bcmdec, "Flushing\n");
+      sts = decif_flush_dec (&bcmdec->decif, 2);
+      if (sts != BC_STS_SUCCESS)
+        GST_ERROR_OBJECT (bcmdec, "Dec flush failed %d", sts);
+      if (!bcmdec->play_pending) {
+        GST_DEBUG_OBJECT (bcmdec, "Stopping\n");
+        sts = decif_stop (&bcmdec->decif);
+        if (sts == BC_STS_SUCCESS) {
+          if (!bcmdec->silent)
+            GST_DEBUG_OBJECT (bcmdec, "stop play success");
+          g_inst_sts->cur_decode = UNKNOWN;
+          g_inst_sts->rendered_frames = 0;
+          GST_DEBUG_OBJECT (bcmdec, "cur_dec set to UNKNOWN");
+
+        } else {
+          GST_ERROR_OBJECT (bcmdec, "stop play failed %d", sts);
+        }
+      }
+      GST_DEBUG_OBJECT (bcmdec, "Stopping threads\n");
+      if (bcmdec->get_rbuf_thread) {
+        GST_DEBUG_OBJECT (bcmdec, "rbuf stop event");
+        if (sem_post (&bcmdec->rbuf_stop_event) == -1)
+          GST_ERROR_OBJECT (bcmdec, "sem_post failed");
+        GST_DEBUG_OBJECT (bcmdec, "waiting for get_rbuf_thread exit");
+        ret = pthread_join (bcmdec->get_rbuf_thread, NULL);
+        GST_DEBUG_OBJECT (bcmdec, "get_rbuf_thread exit - %d errno = %d", ret,
+            errno);
+        bcmdec->get_rbuf_thread = 0;
+      }
+
+      if (bcmdec->recv_thread) {
+        GST_DEBUG_OBJECT (bcmdec, "quit event");
+        if (sem_post (&bcmdec->quit_event) == -1)
+          GST_ERROR_OBJECT (bcmdec, "sem_post failed");
+        GST_DEBUG_OBJECT (bcmdec, "waiting for rec_thread exit");
+        ret = pthread_join (bcmdec->recv_thread, NULL);
+        GST_DEBUG_OBJECT (bcmdec, "thread exit - %d errno = %d", ret, errno);
+        bcmdec->recv_thread = 0;
+      }
+
+      if (bcmdec->push_thread) {
+        GST_DEBUG_OBJECT (bcmdec, "waiting for push_thread exit");
+        ret = pthread_join (bcmdec->push_thread, NULL);
+        GST_DEBUG_OBJECT (bcmdec, "push_thread exit - %d errno = %d", ret,
+            errno);
+        bcmdec->push_thread = 0;
+      }
+
+      break;
+
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      GST_DEBUG_OBJECT (bcmdec, "GST_STATE_CHANGE_PLAYING_TO_PAUSED");
+      break;
+
+    default:
+      GST_DEBUG_OBJECT (bcmdec, "default %d", transition);
+      break;
+  }
+  result =
+      GST_ELEMENT_CLASS (gst_bcm_dec_parent_class)->change_state (element,
+      transition);
+  if (result == GST_STATE_CHANGE_FAILURE) {
+    GST_ERROR_OBJECT (bcmdec, "parent class state change failed");
+    return result;
+  }
+
+  if (transition == GST_STATE_CHANGE_READY_TO_NULL) {
+    GST_DEBUG_OBJECT (bcmdec, "GST_STATE_CHANGE_READY_TO_NULL");
+    sts = gst_bcm_dec_cleanup (bcmdec);
+    if (sts == BC_STS_SUCCESS)
+      GST_DEBUG_OBJECT (bcmdec, "dev close success");
+    else
+      GST_ERROR_OBJECT (bcmdec, "dev close failed %d", sts);
+  }
+
+  return result;
+}
+
+static gboolean
+bcmdec_get_buffer (GstBcmDec * bcmdec, gint size, GstBuffer ** obuf)
+{
+  GstFlowReturn ret;
+  GST_DEBUG_OBJECT (bcmdec, "%s", __func__);
+
+  *obuf = gst_buffer_new_allocate (NULL, size, NULL);
+
+  if (obuf == NULL) {
+    GST_ERROR_OBJECT (bcmdec, "gst_pad_alloc_buffer_and_set_caps failed %d ",
+        ret);
+    return FALSE;
+  }
+#if 0
+  if (((uintptr_t) GST_BUFFER_DATA (*obuf)) % 4)
+    GST_DEBUG_OBJECT (bcmdec, "buf is not aligned");
+#endif
+  return TRUE;
+}
+
+
+static void
+bcmdec_init_procout (GstBcmDec * bcmdec, BC_DTS_PROC_OUT * pout, guint8 * buf)
+{
+  // GSTREAMER only supports Interleaved mode for Interlaced content
+  //if (bcmdec->format_reset)
+  {
+    memset (pout, 0, sizeof (BC_DTS_PROC_OUT));
+    pout->PicInfo.width = bcmdec->output_params.width;
+    pout->PicInfo.height = bcmdec->output_params.height;
+    pout->YbuffSz = bcmdec->output_params.y_size / 4;
+    pout->UVbuffSz = bcmdec->output_params.uv_size / 4;
+
+    pout->PoutFlags = BC_POUT_FLAGS_SIZE;
+#ifdef YV12__
+    pout->PoutFlags |= BC_POUT_FLAGS_YV12;
+#endif
+    if (bcmdec->interlace)
+      pout->PoutFlags |= BC_POUT_FLAGS_INTERLACED;
+
+    if ((bcmdec->output_params.stride) || (bcmdec->interlace)) {
+      pout->PoutFlags |= BC_POUT_FLAGS_STRIDE;
+      if (bcmdec->interlace)
+        pout->StrideSz =
+            bcmdec->output_params.width + 2 * bcmdec->output_params.stride;
+      else
+        pout->StrideSz = bcmdec->output_params.stride;
+    }
+//              bcmdec->format_reset = FALSE;
+  }
+  pout->PoutFlags = pout->PoutFlags & 0xff;
+  pout->Ybuff = (uint8_t *) buf;
+
+  if (pout->UVbuffSz) {
+    if (bcmdec->interlace) {
+      pout->UVbuff = buf + bcmdec->output_params.y_size * 2;
+      if (bcmdec->sec_field) {
+        pout->Ybuff += bcmdec->output_params.width;
+        pout->UVbuff += bcmdec->output_params.width / 2;
+      }
+    } else {
+      pout->UVbuff = buf + bcmdec->output_params.y_size;
+    }
+  } else {
+    pout->UVbuff = NULL;
+    if (bcmdec->interlace) {
+      if (bcmdec->sec_field)
+        pout->Ybuff += bcmdec->output_params.width * 2;
+    }
+  }
+
+  return;
+}
+
+static void
+bcmdec_set_framerate (GstBcmDec * bcmdec, guint32 nFrameRate)
+{
+  gdouble framerate = (gdouble) nFrameRate / 1000;
+
+//      bcmdec->interlace = FALSE;
+
+  if ((framerate) && (bcmdec->output_params.framerate != framerate)) {
+    bcmdec->output_params.framerate = framerate;
+    bcmdec->frame_time =
+        (GstClockTime) (UNITS / bcmdec->output_params.framerate);
+
+    //if (bcmdec->interlace)
+    //      bcmdec->output_params.framerate /= 2;
+
+    GST_DEBUG_OBJECT (bcmdec, "framerate = %f", framerate);
+  }
+}
+
+static void
+bcmdec_set_aspect_ratio (GstBcmDec * bcmdec, BC_PIC_INFO_BLOCK * pic_info)
+{
+  switch (pic_info->aspect_ratio) {
+    case vdecAspectRatioSquare:
+      bcmdec->output_params.aspectratio_x = 1;
+      bcmdec->output_params.aspectratio_y = 1;
+      break;
+    case vdecAspectRatio12_11:
+      bcmdec->output_params.aspectratio_x = 12;
+      bcmdec->output_params.aspectratio_y = 11;
+      break;
+    case vdecAspectRatio10_11:
+      bcmdec->output_params.aspectratio_x = 10;
+      bcmdec->output_params.aspectratio_y = 11;
+      break;
+    case vdecAspectRatio16_11:
+      bcmdec->output_params.aspectratio_x = 16;
+      bcmdec->output_params.aspectratio_y = 11;
+      break;
+    case vdecAspectRatio40_33:
+      bcmdec->output_params.aspectratio_x = 40;
+      bcmdec->output_params.aspectratio_y = 33;
+      break;
+    case vdecAspectRatio24_11:
+      bcmdec->output_params.aspectratio_x = 24;
+      bcmdec->output_params.aspectratio_y = 11;
+      break;
+    case vdecAspectRatio20_11:
+      bcmdec->output_params.aspectratio_x = 20;
+      bcmdec->output_params.aspectratio_y = 11;
+      break;
+    case vdecAspectRatio32_11:
+      bcmdec->output_params.aspectratio_x = 32;
+      bcmdec->output_params.aspectratio_y = 11;
+      break;
+    case vdecAspectRatio80_33:
+      bcmdec->output_params.aspectratio_x = 80;
+      bcmdec->output_params.aspectratio_y = 33;
+      break;
+    case vdecAspectRatio18_11:
+      bcmdec->output_params.aspectratio_x = 18;
+      bcmdec->output_params.aspectratio_y = 11;
+      break;
+    case vdecAspectRatio15_11:
+      bcmdec->output_params.aspectratio_x = 15;
+      bcmdec->output_params.aspectratio_y = 11;
+      break;
+    case vdecAspectRatio64_33:
+      bcmdec->output_params.aspectratio_x = 64;
+      bcmdec->output_params.aspectratio_y = 33;
+      break;
+    case vdecAspectRatio160_99:
+      bcmdec->output_params.aspectratio_x = 160;
+      bcmdec->output_params.aspectratio_y = 99;
+      break;
+    case vdecAspectRatio4_3:
+      bcmdec->output_params.aspectratio_x = 4;
+      bcmdec->output_params.aspectratio_y = 3;
+      break;
+    case vdecAspectRatio16_9:
+      bcmdec->output_params.aspectratio_x = 16;
+      bcmdec->output_params.aspectratio_y = 9;
+      break;
+    case vdecAspectRatio221_1:
+      bcmdec->output_params.aspectratio_x = 221;
+      bcmdec->output_params.aspectratio_y = 1;
+      break;
+    case vdecAspectRatioOther:
+      bcmdec->output_params.aspectratio_x =
+          pic_info->custom_aspect_ratio_width_height & 0x0000ffff;
+      bcmdec->output_params.aspectratio_y =
+          pic_info->custom_aspect_ratio_width_height >> 16;
+      break;
+    case vdecAspectRatioUnknown:
+    default:
+      bcmdec->output_params.aspectratio_x = 0;
+      bcmdec->output_params.aspectratio_y = 0;
+      break;
+  }
+
+  // Use Demux Aspect ratio first before falling back to HW ratio
+  if (bcmdec->input_par_x != 0) {
+    bcmdec->output_params.aspectratio_x = bcmdec->input_par_x;
+    bcmdec->output_params.aspectratio_y = bcmdec->input_par_y;
+  } else if (bcmdec->output_params.aspectratio_x == 0) {
+    bcmdec->output_params.aspectratio_x = 1;
+    bcmdec->output_params.aspectratio_y = 1;
+  }
+
+  GST_DEBUG_OBJECT (bcmdec, "dec_par x = %d",
+      bcmdec->output_params.aspectratio_x);
+  GST_DEBUG_OBJECT (bcmdec, "dec_par y = %d",
+      bcmdec->output_params.aspectratio_y);
+}
+
+static gboolean
+bcmdec_format_change (GstBcmDec * bcmdec, BC_PIC_INFO_BLOCK * pic_info)
+{
+  gboolean result = FALSE;
+  GST_DEBUG_OBJECT (bcmdec, "Got format Change to %dx%d", pic_info->width,
+      pic_info->height);
+
+  if (pic_info->height == 1088)
+    pic_info->height = 1080;
+
+  bcmdec->output_params.width = pic_info->width;
+  bcmdec->output_params.height = pic_info->height;
+
+  bcmdec_set_aspect_ratio (bcmdec, pic_info);
+
+  // Interlaced
+  if ((pic_info->flags & VDEC_FLAG_INTERLACED_SRC) == VDEC_FLAG_INTERLACED_SRC)
+    bcmdec->interlace = TRUE;
+  else
+    bcmdec->interlace = FALSE;
+
+  if ((bcmdec->input_format == BC_MSUBTYPE_AVC1)
+      || (bcmdec->input_format == BC_MSUBTYPE_H264)) {
+    if (!bcmdec->interlace && (pic_info->pulldown == vdecFrame_X1)
+        && (pic_info->flags & VDEC_FLAG_FIELDPAIR)
+        && (pic_info->flags & VDEC_FLAG_INTERLACED_SRC))
+      bcmdec->interlace = TRUE;
+  }
+
+  result = bcmdec_negotiate_format (bcmdec);
+  if (!bcmdec->silent) {
+    if (result)
+      GST_DEBUG_OBJECT (bcmdec, "negotiate_format success");
+    else
+      GST_ERROR_OBJECT (bcmdec, "negotiate_format failed");
+  }
+  //bcmdec->format_reset = TRUE;
+  return result;
+}
+
+static int
+bcmdec_wait_for_event (GstBcmDec * bcmdec)
+{
+  int ret = 0, i = 0;
+  sem_t *event_list[] = { &bcmdec->play_event, &bcmdec->quit_event };
+
+  GST_DEBUG_OBJECT (bcmdec, "Waiting for event\n");
+
+  while (1) {
+    for (i = 0; i < 2; i++) {
+
+      ret = sem_trywait (event_list[i]);
+      if (ret == 0) {
+        GST_DEBUG_OBJECT (bcmdec, "event wait over in Rx thread ret = %d", i);
+        return i;
+      } else if (errno == EINTR) {
+        break;
+      }
+      if (bcmdec->streaming)
+        break;
+    }
+    usleep (10);
+  }
+}
+
+static void
+bcmdec_flush_gstbuf_queue (GstBcmDec * bcmdec)
+{
+  GSTBUF_LIST *gst_queue_element;
+  int sval;
+
+  do {
+    gst_queue_element = bcmdec_rem_buf (bcmdec);
+    if (gst_queue_element) {
+      if (gst_queue_element->gstbuf) {
+        gst_buffer_unref (gst_queue_element->gstbuf);
+        bcmdec_put_que_mem_buf (bcmdec, gst_queue_element);
+      }
+    } else {
+      GST_DEBUG_OBJECT (bcmdec, "no gst_queue_element");
+    }
+  } while (gst_queue_element && gst_queue_element->gstbuf);
+
+  // Re-initialize the buf_event semaphone since we have just flushed the entire queued
+  sem_destroy (&bcmdec->buf_event);
+  sem_init (&bcmdec->buf_event, 0, 0);
+  sem_getvalue (&bcmdec->buf_event, &sval);
+  GST_DEBUG_OBJECT (bcmdec, "sem value after flush is %d", sval);
+}
+
+static void *
+bcmdec_process_push (void *ctx)
+{
+  GstBcmDec *bcmdec = (GstBcmDec *) ctx;
+  GSTBUF_LIST *gst_queue_element = NULL;
+  gboolean result = FALSE, done = FALSE;
+  struct timespec ts;
+  gint ret;
+
+  ts.tv_sec = time (NULL);
+  ts.tv_nsec = 30 * 1000000;
+
+  if (!bcmdec->silent)
+    GST_DEBUG_OBJECT (bcmdec, "process push starting ");
+
+  while (1) {
+
+    if (!bcmdec->recv_thread && !bcmdec->streaming) {
+      if (!bcmdec->silent)
+        GST_DEBUG_OBJECT (bcmdec, "process push exiting..");
+      break;
+    }
+
+    ret = sem_timedwait (&bcmdec->push_start_event, &ts);
+    if (ret < 0) {
+      if (errno == ETIMEDOUT)
+        continue;
+      else if (errno == EINTR)
+        break;
+    } else {
+      GST_DEBUG_OBJECT (bcmdec, "push_start wait over");
+      done = FALSE;
+    }
+
+    ts.tv_sec = time (NULL) + 1;
+    ts.tv_nsec = 0;
+
+    while (bcmdec->streaming && !done) {
+      ret = sem_timedwait (&bcmdec->buf_event, &ts);
+      if (ret < 0) {
+        switch (errno) {
+          case ETIMEDOUT:
+            if (bcmdec->streaming) {
+              continue;
+            } else {
+              done = TRUE;
+              GST_DEBUG_OBJECT (bcmdec, "TOB ");
+              break;
+            }
+          case EINTR:
+            GST_DEBUG_OBJECT (bcmdec, "Sig interrupt ");
+            done = TRUE;
+            break;
+
+          default:
+            GST_ERROR_OBJECT (bcmdec, "sem wait failed %d ", errno);
+            done = TRUE;
+            break;
+        }
+      }
+      if (ret == 0) {
+        GST_DEBUG_OBJECT (bcmdec, "Starting to PUSH ");
+        gst_queue_element = bcmdec_rem_buf (bcmdec);
+        if (gst_queue_element) {
+          if (gst_queue_element->gstbuf) {
+            GST_DEBUG_OBJECT (bcmdec, "Trying to PUSH ");
+            result = gst_pad_push (bcmdec->srcpad, gst_queue_element->gstbuf);
+            if (result != GST_FLOW_OK) {
+              GST_DEBUG_OBJECT (bcmdec, "exiting, failed to push sts = %d",
+                  result);
+              gst_buffer_unref (gst_queue_element->gstbuf);
+              done = TRUE;
+            } else {
+              GST_DEBUG_OBJECT (bcmdec, "PUSHED, Qcnt:%d, Rcnt:%d",
+                  bcmdec->gst_que_cnt, bcmdec->gst_padbuf_que_cnt);
+              if ((g_inst_sts->rendered_frames++ > THUMBNAIL_FRAMES)
+                  && (g_inst_sts->cur_decode != PLAYBACK)) {
+                g_inst_sts->cur_decode = PLAYBACK;
+                GST_DEBUG_OBJECT (bcmdec, "cur_dec set to PLAYBACK");
+              }
+            }
+          } else {
+            /*exit *//* NULL value of gstbuf indicates EOS */
+            gst_pad_push_event (bcmdec->srcpad, bcmdec->ev_eos);
+            gst_event_unref (bcmdec->ev_eos);
+            done = TRUE;
+            bcmdec->streaming = FALSE;
+            GST_DEBUG_OBJECT (bcmdec, "eos sent, cnt:%d", bcmdec->gst_que_cnt);
+          }
+          bcmdec_put_que_mem_buf (bcmdec, gst_queue_element);
+        } else
+          GST_DEBUG_OBJECT (bcmdec, "NO BUFFER FOUND");
+      }
+      if (bcmdec->flushing && bcmdec->push_exit) {
+        GST_DEBUG_OBJECT (bcmdec, "push -flush exit");
+        break;
+      }
+    }
+    if (bcmdec->flushing) {
+      GST_DEBUG_OBJECT (bcmdec, "flushing gstbuf queue");
+      bcmdec_flush_gstbuf_queue (bcmdec);
+      if (sem_post (&bcmdec->push_stop_event) == -1)
+        GST_ERROR_OBJECT (bcmdec, "push_stop sem_post failed");
+      g_inst_sts->rendered_frames = 0;
+    }
+  }
+  bcmdec_flush_gstbuf_queue (bcmdec);
+  GST_DEBUG_OBJECT (bcmdec, "process push exiting.. ");
+  pthread_exit ((void *) &result);
+}
+
+static void *
+bcmdec_process_output (void *ctx)
+{
+  BC_DTS_PROC_OUT pout;
+  BC_STATUS sts = BC_STS_SUCCESS;
+  GstBcmDec *bcmdec = (GstBcmDec *) ctx;
+  GstBuffer *gstbuf = NULL;
+  gboolean rx_flush = FALSE, bEOS = FALSE;
+  const guint first_picture = 3;
+  guint32 pic_number = 0;
+  GstClockTime clock_time = 0;
+  gboolean first_frame_after_seek = FALSE;
+  GstClockTime cur_stream_time_diff = 0;
+  int wait_cnt = 0;
+  guint32 nextPicNumFlags = 0;
+  GstMapInfo info;
+
+  gboolean is_paused = FALSE;
+
+  GSTBUF_LIST *gst_queue_element = NULL;
+
+  if (!bcmdec->silent)
+    GST_DEBUG_OBJECT (bcmdec, "Rx thread started");
+
+  while (1) {
+    if (1 == bcmdec_wait_for_event (bcmdec)) {
+      if (!bcmdec->silent)
+        GST_DEBUG_OBJECT (bcmdec, "quit event set, exit");
+      break;
+    }
+
+    GST_DEBUG_OBJECT (bcmdec, "wait over streaming = %d", bcmdec->streaming);
+    while (bcmdec->streaming && !bcmdec->last_picture_set) {
+      uint32_t rll;
+      gboolean tmp;
+      guint8 *data_ptr;
+
+      GST_DEBUG_OBJECT (bcmdec, "Getting Status");
+      // NAREN FIXME - This is HARDCODED right now till we get HW PAUSE and RESUME working from the driver
+      decif_get_drv_status (&(bcmdec->decif), &tmp, &rll, &nextPicNumFlags);
+      if (rll >= 12 && !is_paused) {
+        GST_DEBUG_OBJECT (bcmdec, "HW PAUSE with RLL %u", rll);
+        decif_pause (&(bcmdec->decif), TRUE);
+        is_paused = TRUE;
+      } else if (rll < 12 && is_paused) {
+        GST_DEBUG_OBJECT (bcmdec, "HW RESUME with RLL %u", rll);
+        decif_pause (&(bcmdec->decif), FALSE);
+        is_paused = FALSE;
+      }
+
+      if (rll == 0) {
+        GST_DEBUG_OBJECT (bcmdec, "No Picture Found");
+        usleep (5 * 1000);
+        // Check if there was an EOS signalled
+        decif_get_eos (&bcmdec->decif, &bEOS);
+        if (!bEOS)
+          continue;
+      }
+
+      if (gstbuf == NULL) {
+        if (!bcmdec->rbuf_thread_running) {
+          gint size =
+              bcmdec->output_params.width * bcmdec->output_params.height *
+              BUF_MULT;
+          if (!bcmdec_get_buffer (bcmdec, size, &gstbuf)) {
+            usleep (30 * 1000);
+            continue;
+          }
+          GST_DEBUG_OBJECT (bcmdec, "got default buffer, going to proc output");
+        } else {
+          if (gst_queue_element) {
+            if (gst_queue_element->gstbuf)
+              gst_buffer_unref (gst_queue_element->gstbuf);
+            bcmdec_put_que_mem_buf (bcmdec, gst_queue_element);
+            gst_queue_element = NULL;
+          }
+
+          gst_queue_element = bcmdec_rem_padbuf (bcmdec);
+          if (!gst_queue_element) {
+            GST_DEBUG_OBJECT (bcmdec, "rbuf queue empty");
+            usleep (10 * 1000);
+            continue;
+          }
+
+          gstbuf = gst_queue_element->gstbuf;
+          if (!gstbuf) {
+            bcmdec_put_que_mem_buf (bcmdec, gst_queue_element);
+            gst_queue_element = NULL;
+            usleep (10 * 1000);
+            continue;
+          }
+          GST_DEBUG_OBJECT (bcmdec, "got rbuf, going to proc output");
+        }
+      } else
+        GST_DEBUG_OBJECT (bcmdec, "re-using rbuf, going to proc output");
+
+      if (!gst_buffer_map (gstbuf, &info, GST_MAP_WRITE)) {
+        GST_ERROR_OBJECT (bcmdec, "Failed to map buffer");
+        continue;
+      }
+      data_ptr = info.data;
+      bcmdec_init_procout (bcmdec, &pout, data_ptr);
+      gst_buffer_unmap (gstbuf, &info);
+
+      rx_flush = TRUE;
+      pout.PicInfo.picture_number = 0;
+      // For interlaced content, if I am holding a buffer but the next buffer is not from the same picture
+      // i.e. the second field, then assume that this is a case of one field per picture and deliver this field
+      // Don't deliver the one with picture number of 0
+      if (bcmdec->sec_field) {
+        if (((nextPicNumFlags & 0x0FFFFFFF) - first_picture) != pic_number) {
+          if (pic_number == 0)
+            gst_buffer_unref (gstbuf);
+          else if (gst_queue_element) {
+            GST_BUFFER_FLAG_SET (gstbuf, GST_VIDEO_BUFFER_FLAG_ONEFIELD);
+            gst_queue_element->gstbuf = gstbuf;
+            bcmdec_ins_buf (bcmdec, gst_queue_element);
+            bcmdec->prev_pic = pic_number;
+            gst_queue_element = NULL;
+          } else {
+            GST_DEBUG_OBJECT (bcmdec, "SOMETHING BAD HAPPENED\n");
+            gst_buffer_unref (gstbuf);
+          }
+          gstbuf = NULL;
+          bcmdec->sec_field = FALSE;;
+          continue;
+        }
+      }
+      if (bEOS) {
+        if (gstbuf) {
+          gst_buffer_unref (gstbuf);
+          gstbuf = NULL;
+        }
+        if (gst_queue_element) {
+          gst_queue_element->gstbuf = NULL;
+          bcmdec_ins_buf (bcmdec, gst_queue_element);
+          gst_queue_element = NULL;
+        } else {
+          GST_DEBUG_OBJECT (bcmdec, "queue element failed");
+        }
+        GST_DEBUG_OBJECT (bcmdec, "last picture set ");
+        bcmdec->last_picture_set = TRUE;
+        continue;
+      }
+      sts = DtsProcOutput (bcmdec->decif.hdev, PROC_TIMEOUT, &pout);
+      GST_DEBUG_OBJECT (bcmdec, "procoutput status %d", sts);
+      switch (sts) {
+        case BC_STS_FMT_CHANGE:
+          if (!bcmdec->silent)
+            GST_DEBUG_OBJECT (bcmdec, "procout ret FMT");
+          if ((pout.PoutFlags & BC_POUT_FLAGS_PIB_VALID) &&
+              (pout.PoutFlags & BC_POUT_FLAGS_FMT_CHANGE)) {
+            if (bcmdec_format_change (bcmdec, &pout.PicInfo)) {
+              GST_DEBUG_OBJECT (bcmdec, "format change success");
+              //bcmdec->frame_time = (GstClockTime)(UNITS / bcmdec->output_params.framerate);
+              bcmdec->last_spes_time = 0;
+              bcmdec->prev_clock_time = 0;
+              cur_stream_time_diff = 0;
+              first_frame_after_seek = TRUE;
+            } else {
+              GST_DEBUG_OBJECT (bcmdec, "format change failed");
+            }
+          }
+          gst_buffer_unref (gstbuf);
+          gstbuf = NULL;
+          bcmdec->sec_field = FALSE;
+
+          if (sem_post (&bcmdec->rbuf_start_event) == -1)
+            GST_ERROR_OBJECT (bcmdec, "rbuf sem_post failed");
+
+          //should modify to wait event
+          wait_cnt = 0;
+          while (!bcmdec->rbuf_thread_running && (wait_cnt < 5000)) {
+            usleep (1000);
+            wait_cnt++;
+          }
+          GST_DEBUG_OBJECT (bcmdec,
+              "format change wait for rbuf thread start wait_cnt:%d", wait_cnt);
+
+          break;
+        case BC_STS_SUCCESS:
+          if (!(pout.PoutFlags & BC_POUT_FLAGS_PIB_VALID)) {
+            if (!bcmdec->silent)
+              GST_DEBUG_OBJECT (bcmdec, "procout ret PIB miss %d",
+                  pout.PicInfo.picture_number - 3);
+            continue;
+          }
+
+          bcmdec_set_framerate (bcmdec, pout.PicInfo.frame_rate);
+          pic_number = pout.PicInfo.picture_number - first_picture;
+
+          if (!bcmdec->silent)
+            GST_DEBUG_OBJECT (bcmdec, "pic_number from HW is %u",
+                pout.PicInfo.picture_number);
+
+          if (bcmdec->flushing) {
+            GST_DEBUG_OBJECT (bcmdec, "flushing discard, pic = %d", pic_number);
+            continue;
+          }
+
+          if (bcmdec->prev_pic + 1 < pic_number) {
+            if (!bcmdec->silent)
+              GST_DEBUG_OBJECT (bcmdec, "LOST PICTURE pic_no = %d, prev = %d",
+                  pic_number, bcmdec->prev_pic);
+          }
+
+          if (!bcmdec->interlace || bcmdec->sec_field) {
+            GST_DEBUG_OBJECT (bcmdec, "Progressive or Second Field");
+            GST_BUFFER_OFFSET (gstbuf) = 0;
+            GST_BUFFER_TIMESTAMP (gstbuf) =
+                bcmdec_get_time_stamp (bcmdec, pic_number,
+                pout.PicInfo.timeStamp);
+            GST_BUFFER_DURATION (gstbuf) = bcmdec->frame_time;
+            if (bcmdec->gst_clock) {
+              clock_time = gst_clock_get_time (bcmdec->gst_clock);
+              if (first_frame_after_seek) {
+                bcmdec->prev_clock_time = clock_time;
+                first_frame_after_seek = FALSE;
+                cur_stream_time_diff = 0;
+              }
+              if (bcmdec->prev_clock_time > clock_time)
+                bcmdec->prev_clock_time = 0;
+              cur_stream_time_diff += clock_time - bcmdec->prev_clock_time;
+              bcmdec->cur_stream_time =
+                  cur_stream_time_diff + bcmdec->base_clock_time;
+              bcmdec->prev_clock_time = clock_time;
+              if ((bcmdec->last_spes_time < bcmdec->cur_stream_time) &&
+                  (!bcmdec->catchup_on) && (pout.PicInfo.timeStamp)) {
+                bcmdec->catchup_on = TRUE;
+                decif_decode_catchup (&bcmdec->decif, TRUE);
+              } else if (bcmdec->catchup_on) {
+                decif_decode_catchup (&bcmdec->decif, FALSE);
+                bcmdec->catchup_on = FALSE;
+              }
+            }
+          }
+
+          if (!bcmdec->interlace || bcmdec->sec_field) {
+            if (gst_queue_element) {
+              // If interlaced, set the GST_VIDEO_BUFFER_TFF flags
+              if (bcmdec->sec_field)
+                GST_BUFFER_FLAG_SET (gstbuf, GST_VIDEO_BUFFER_FLAG_TFF);
+              gst_queue_element->gstbuf = gstbuf;
+              bcmdec_ins_buf (bcmdec, gst_queue_element);
+              bcmdec->prev_pic = pic_number;
+            } else {
+              GST_ERROR_OBJECT (bcmdec, "This CANNOT HAPPEN");  //pending error recovery
+            }
+            gstbuf = NULL;
+            bcmdec->sec_field = FALSE;
+            gst_queue_element = NULL;
+          } else {
+            GST_DEBUG_OBJECT (bcmdec, "Wait for second field");
+            bcmdec->sec_field = TRUE;
+          }
+          break;
+
+        case BC_STS_TIMEOUT:
+          GST_DEBUG_OBJECT (bcmdec,
+              "procout timeout QCnt:%d, RCnt:%d, Paused:%d",
+              bcmdec->gst_que_cnt, bcmdec->gst_padbuf_que_cnt, bcmdec->paused);
+          break;
+        case BC_STS_IO_XFR_ERROR:
+          GST_DEBUG_OBJECT (bcmdec, "procout xfer error");
+          break;
+        case BC_STS_IO_USER_ABORT:
+        case BC_STS_IO_ERROR:
+          bcmdec->streaming = FALSE;
+          GST_DEBUG_OBJECT (bcmdec, "ABORT sts = %d", sts);
+          if (gstbuf) {
+            gst_buffer_unref (gstbuf);
+            gstbuf = NULL;
+          }
+          break;
+        case BC_STS_NO_DATA:
+          GST_DEBUG_OBJECT (bcmdec, "procout no data");
+          // Check for EOS
+          decif_get_eos (&bcmdec->decif, &bEOS);
+          if (bEOS) {
+            if (gstbuf) {
+              gst_buffer_unref (gstbuf);
+              gstbuf = NULL;
+            }
+            if (gst_queue_element) {
+              gst_queue_element->gstbuf = NULL;
+              bcmdec_ins_buf (bcmdec, gst_queue_element);
+              gst_queue_element = NULL;
+            } else {
+              GST_DEBUG_OBJECT (bcmdec, "queue element failed");
+            }
+            GST_DEBUG_OBJECT (bcmdec, "last picture set ");
+            bcmdec->last_picture_set = TRUE;
+          }
+          break;
+        default:
+          GST_DEBUG_OBJECT (bcmdec, "unhandled status from Procout sts %d",
+              sts);
+          if (gstbuf) {
+            gst_buffer_unref (gstbuf);
+            gstbuf = NULL;
+          }
+          break;
+      }
+    }
+    if (gstbuf) {
+      gst_buffer_unref (gstbuf);
+      gstbuf = NULL;
+    }
+    if (gst_queue_element) {
+      bcmdec_put_que_mem_buf (bcmdec, gst_queue_element);
+      gst_queue_element = NULL;
+    }
+    if (rx_flush) {
+      if (!bcmdec->flushing) {
+        GST_DEBUG_OBJECT (bcmdec, "DtsFlushRxCapture called");
+//                              sts = decif_flush_rxbuf(&bcmdec->decif, FALSE);
+//                              if (sts != BC_STS_SUCCESS)
+//                                      GST_DEBUG_OBJECT(bcmdec, "DtsFlushRxCapture failed");
+      }
+      rx_flush = FALSE;
+      if (bcmdec->flushing) {
+        if (sem_post (&bcmdec->recv_stop_event) == -1)
+          GST_ERROR_OBJECT (bcmdec, "recv_stop sem_post failed");
+      }
+      GST_DEBUG_OBJECT (bcmdec, "DtsFlushRxCapture Done");
+    }
+  }
+  GST_DEBUG_OBJECT (bcmdec, "Rx thread exiting ..");
+  pthread_exit ((void *) &sts);
+}
+
+static gboolean
+bcmdec_start_push_thread (GstBcmDec * bcmdec)
+{
+  gboolean result = TRUE;
+  pthread_attr_t thread_attr;
+  gint ret = 0;
+
+  pthread_attr_init (&thread_attr);
+  pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_JOINABLE);
+  pthread_create (&bcmdec->push_thread, &thread_attr, bcmdec_process_push,
+      bcmdec);
+  pthread_attr_destroy (&thread_attr);
+
+  if (!bcmdec->push_thread) {
+    GST_ERROR_OBJECT (bcmdec, "Failed to create PushThread");
+    result = FALSE;
+  } else {
+    GST_DEBUG_OBJECT (bcmdec, "Success to create PushThread");
+  }
+
+  ret = sem_init (&bcmdec->buf_event, 0, 0);
+  if (ret != 0) {
+    GST_ERROR_OBJECT (bcmdec, "play event init failed");
+    result = FALSE;
+  }
+
+  ret = sem_init (&bcmdec->push_start_event, 0, 0);
+  if (ret != 0) {
+    GST_ERROR_OBJECT (bcmdec, "play event init failed");
+    result = FALSE;
+  }
+
+  ret = sem_init (&bcmdec->push_stop_event, 0, 0);
+  if (ret != 0) {
+    GST_ERROR_OBJECT (bcmdec, "push_stop event init failed");
+    result = FALSE;
+  }
+
+  return result;
+}
+
+static gboolean
+bcmdec_start_recv_thread (GstBcmDec * bcmdec)
+{
+  gboolean result = TRUE;
+  gint ret = 0;
+  pthread_attr_t thread_attr;
+
+  if (!bcmdec_alloc_mem_buf_que_pool (bcmdec))
+    GST_ERROR_OBJECT (bcmdec, "pool alloc failed/n");
+
+  ret = sem_init (&bcmdec->play_event, 0, 0);
+  if (ret != 0) {
+    GST_ERROR_OBJECT (bcmdec, "play event init failed");
+    result = FALSE;
+  }
+
+  ret = sem_init (&bcmdec->quit_event, 0, 0);
+  if (ret != 0) {
+    GST_ERROR_OBJECT (bcmdec, "play event init failed");
+    result = FALSE;
+  }
+
+  ret = sem_init (&bcmdec->recv_stop_event, 0, 0);
+  if (ret != 0) {
+    GST_ERROR_OBJECT (bcmdec, "recv_stop event init failed");
+    result = FALSE;
+  }
+
+  pthread_attr_init (&thread_attr);
+  pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_JOINABLE);
+  pthread_create (&bcmdec->recv_thread, &thread_attr, bcmdec_process_output,
+      bcmdec);
+  pthread_attr_destroy (&thread_attr);
+
+  if (!bcmdec->recv_thread) {
+    GST_ERROR_OBJECT (bcmdec, "Failed to create RxThread");
+    result = FALSE;
+  } else {
+    GST_DEBUG_OBJECT (bcmdec, "Success to create RxThread");
+  }
+
+  return result;
+}
+
+static GstClockTime
+bcmdec_get_time_stamp (GstBcmDec * bcmdec, guint32 pic_no,
+    GstClockTime spes_time)
+{
+  GstClockTime time_stamp = 0;
+  GstClockTime frame_time =
+      (GstClockTime) (UNITS / bcmdec->output_params.framerate);
+
+  if (bcmdec->enable_spes) {
+    if (spes_time) {
+      time_stamp = spes_time;
+      if (bcmdec->spes_frame_cnt && bcmdec->last_output_spes_time) {
+        bcmdec->frame_time =
+            (time_stamp -
+            bcmdec->last_output_spes_time) / bcmdec->spes_frame_cnt;
+        bcmdec->spes_frame_cnt = 0;
+      }
+      if (bcmdec->frame_time > 0)
+        frame_time = bcmdec->frame_time;
+      bcmdec->spes_frame_cnt++;
+      bcmdec->last_output_spes_time = bcmdec->last_spes_time = time_stamp;
+    } else {
+      if (bcmdec->frame_time > 0)
+        frame_time = bcmdec->frame_time;
+      bcmdec->last_spes_time += frame_time;
+      time_stamp = bcmdec->last_spes_time;
+      bcmdec->spes_frame_cnt++;
+    }
+  } else {
+    time_stamp = (GstClockTime) (bcmdec->base_time + frame_time * pic_no);
+  }
+
+  if (!bcmdec->enable_spes) {
+    if (bcmdec->interlace) {
+      if (bcmdec->prev_pic == pic_no)
+        bcmdec->rpt_pic_cnt++;
+      time_stamp += bcmdec->rpt_pic_cnt * frame_time;
+    }
+  }
+
+  return time_stamp;
+}
+
+static void
+bcmdec_process_flush_stop (GstBcmDec * bcmdec)
+{
+  bcmdec->ses_change = TRUE;
+  bcmdec->base_time = 0;
+  bcmdec->flushing = FALSE;
+  bcmdec->streaming = TRUE;
+  bcmdec->rpt_pic_cnt = 0;
+
+  GST_DEBUG_OBJECT (bcmdec, "flush stop started");
+
+  if (sem_post (&bcmdec->play_event) == -1)
+    GST_ERROR_OBJECT (bcmdec, "sem_post failed");
+
+  bcmdec->push_exit = FALSE;
+
+  if (sem_post (&bcmdec->push_start_event) == -1)
+    GST_ERROR_OBJECT (bcmdec, "push_start post failed");
+
+  GST_DEBUG_OBJECT (bcmdec, "flush stop complete");
+
+}
+
+static void
+bcmdec_process_flush_start (GstBcmDec * bcmdec)
+{
+  gint ret = 1;
+  BC_STATUS sts = BC_STS_SUCCESS;
+  struct timespec ts;
+
+  ts.tv_sec = time (NULL) + 5;
+  ts.tv_nsec = 0;
+
+  bcmdec->flushing = TRUE;
+  bcmdec->streaming = FALSE;
+
+  ret = sem_timedwait (&bcmdec->recv_stop_event, &ts);
+  if (ret < 0) {
+    switch (errno) {
+      case ETIMEDOUT:
+        GST_DEBUG_OBJECT (bcmdec, "recv_stop_event sig timed out ");
+        break;
+      case EINTR:
+        GST_DEBUG_OBJECT (bcmdec, "Sig interrupt ");
+        break;
+      default:
+        GST_ERROR_OBJECT (bcmdec, "sem wait failed %d ", errno);
+        break;
+    }
+  }
+
+  bcmdec->push_exit = TRUE;
+
+  ret = sem_timedwait (&bcmdec->push_stop_event, &ts);
+  if (ret < 0) {
+    switch (errno) {
+      case ETIMEDOUT:
+        GST_DEBUG_OBJECT (bcmdec, "push_stop_event sig timed out ");
+        break;
+      case EINTR:
+        GST_DEBUG_OBJECT (bcmdec, "Sig interrupt ");
+        break;
+      default:
+        GST_ERROR_OBJECT (bcmdec, "sem wait failed %d ", errno);
+        break;
+    }
+  }
+  sts = decif_flush_dec (&bcmdec->decif, 2);
+  if (sts != BC_STS_SUCCESS)
+    GST_ERROR_OBJECT (bcmdec, "flush_dec failed sts %d", sts);
+}
+
+static BC_STATUS
+gst_bcm_dec_cleanup (GstBcmDec * bcmdec)
+{
+  BC_STATUS sts = BC_STS_SUCCESS;
+
+  GST_DEBUG_OBJECT (bcmdec, "gst_bcm_dec_cleanup - enter");
+  bcmdec->streaming = FALSE;
+
+  bcmdec_release_mem_buf_que_pool (bcmdec);
+//      bcmdec_release_mem_rbuf_que_pool(bcmdec);
+
+  if (bcmdec->decif.hdev)
+    sts = decif_close (&bcmdec->decif);
+
+  sem_destroy (&bcmdec->quit_event);
+  sem_destroy (&bcmdec->play_event);
+  sem_destroy (&bcmdec->push_start_event);
+  sem_destroy (&bcmdec->buf_event);
+  sem_destroy (&bcmdec->rbuf_start_event);
+  sem_destroy (&bcmdec->rbuf_stop_event);
+  sem_destroy (&bcmdec->rbuf_ins_event);
+  sem_destroy (&bcmdec->push_stop_event);
+  sem_destroy (&bcmdec->recv_stop_event);
+
+  pthread_mutex_destroy (&bcmdec->gst_buf_que_lock);
+  pthread_mutex_destroy (&bcmdec->gst_padbuf_que_lock);
+  //pthread_mutex_destroy(&bcmdec->fn_lock);
+  if (bcmdec->codec_params.sps_pps_buf) {
+    free (bcmdec->codec_params.sps_pps_buf);
+    bcmdec->codec_params.sps_pps_buf = NULL;
+  }
+
+  if (bcmdec->dest_buf) {
+    free (bcmdec->dest_buf);
+    bcmdec->dest_buf = NULL;
+  }
+//      if (bcmdec->vc1_dest_buffer) {
+//              free(bcmdec->vc1_dest_buffer);
+//              bcmdec->vc1_dest_buffer = NULL;
+//      }
+
+  if (bcmdec->gst_clock) {
+    gst_object_unref (bcmdec->gst_clock);
+    bcmdec->gst_clock = NULL;
+  }
+
+  if (sem_post (&g_inst_sts->inst_ctrl_event) == -1)
+    GST_ERROR_OBJECT (bcmdec, "inst_ctrl_event post failed");
+  else
+    GST_DEBUG_OBJECT (bcmdec, "inst_ctrl_event posted");
+
+  return sts;
+}
+
+static void
+bcmdec_reset (GstBcmDec * bcmdec)
+{
+  bcmdec->dec_ready = FALSE;
+  bcmdec->streaming = FALSE;
+  bcmdec->format_reset = TRUE;
+  bcmdec->interlace = FALSE;
+
+  bcmdec->output_params.width = 720;
+  bcmdec->output_params.height = 480;
+  bcmdec->output_params.framerate = 29;
+  bcmdec->output_params.aspectratio_x = 16;
+  bcmdec->output_params.aspectratio_y = 9;
+  bcmdec->output_params.clr_space = BUF_MODE;
+  if (bcmdec->output_params.clr_space == MODE420) {     /* MODE420 */
+    bcmdec->output_params.y_size = 720 * 480;
+    bcmdec->output_params.uv_size = 720 * 480 / 2;
+  } else {                      /* MODE422_YUV */
+    bcmdec->output_params.y_size = 720 * 480 * 2;
+    bcmdec->output_params.uv_size = 0;
+  }
+
+  bcmdec->output_params.stride = 0;
+
+  bcmdec->base_time = 0;
+  bcmdec->fhnd = NULL;
+
+  bcmdec->play_pending = FALSE;
+
+  bcmdec->gst_buf_que_hd = NULL;
+  bcmdec->gst_buf_que_tl = NULL;
+  bcmdec->gst_que_cnt = 0;
+  bcmdec->last_picture_set = FALSE;
+  bcmdec->gst_buf_que_sz = GST_BUF_LIST_POOL_SZ;
+  bcmdec->gst_padbuf_que_sz = GST_RENDERER_BUF_POOL_SZ;
+  bcmdec->rbuf_thread_running = FALSE;
+
+  bcmdec->insert_start_code = FALSE;
+  bcmdec->codec_params.sps_pps_buf = NULL;
+
+  bcmdec->input_framerate = 0;
+  bcmdec->input_par_x = 0;
+  bcmdec->input_par_y = 0;
+  bcmdec->prev_pic = -1;
+
+  bcmdec->codec_params.inside_buffer = TRUE;
+  bcmdec->codec_params.consumed_offset = 0;
+  bcmdec->codec_params.strtcode_offset = 0;
+  bcmdec->codec_params.nal_sz = 0;
+  bcmdec->codec_params.pps_size = 0;
+  bcmdec->codec_params.nal_size_bytes = 4;
+
+  bcmdec->paused = FALSE;
+
+  bcmdec->flushing = FALSE;
+  bcmdec->ses_nbr = 0;
+  bcmdec->insert_pps = TRUE;
+  bcmdec->ses_change = FALSE;
+
+  bcmdec->push_exit = FALSE;
+
+  bcmdec->suspend_mode = FALSE;
+  bcmdec->gst_clock = NULL;
+  bcmdec->rpt_pic_cnt = 0;
+
+  //bcmdec->enable_spes = FALSE;
+  bcmdec->enable_spes = TRUE;
+  bcmdec->dest_buf = NULL;
+  bcmdec->catchup_on = FALSE;
+  bcmdec->last_output_spes_time = 0;
+
+  pthread_mutex_init (&bcmdec->gst_buf_que_lock, NULL);
+  pthread_mutex_init (&bcmdec->gst_padbuf_que_lock, NULL);
+  //pthread_mutex_init(&bcmdec->fn_lock,NULL);
+}
+
+static void
+bcmdec_put_que_mem_buf (GstBcmDec * bcmdec, GSTBUF_LIST * gst_queue_element)
+{
+  pthread_mutex_lock (&bcmdec->gst_buf_que_lock);
+
+  gst_queue_element->next = bcmdec->gst_mem_buf_que_hd;
+  bcmdec->gst_mem_buf_que_hd = gst_queue_element;
+
+  bcmdec->gst_que_cnt++;
+  GST_DEBUG_OBJECT (bcmdec, "mem pool inc is %u", bcmdec->gst_que_cnt);
+
+  pthread_mutex_unlock (&bcmdec->gst_buf_que_lock);
+}
+
+static GSTBUF_LIST *
+bcmdec_get_que_mem_buf (GstBcmDec * bcmdec)
+{
+  GSTBUF_LIST *gst_queue_element = NULL;
+
+  pthread_mutex_lock (&bcmdec->gst_buf_que_lock);
+
+  gst_queue_element = bcmdec->gst_mem_buf_que_hd;
+  if (gst_queue_element) {
+    bcmdec->gst_mem_buf_que_hd = bcmdec->gst_mem_buf_que_hd->next;
+    bcmdec->gst_que_cnt--;
+
+    GST_DEBUG_OBJECT (bcmdec, "mem pool dec is %u", bcmdec->gst_que_cnt);
+  }
+
+  pthread_mutex_unlock (&bcmdec->gst_buf_que_lock);
+
+  return gst_queue_element;
+}
+
+static gboolean
+bcmdec_alloc_mem_buf_que_pool (GstBcmDec * bcmdec)
+{
+  GSTBUF_LIST *gst_queue_element = NULL;
+  guint i = 0;
+
+  bcmdec->gst_mem_buf_que_hd = NULL;
+  while (i++ < bcmdec->gst_buf_que_sz) {
+    if (!(gst_queue_element = (GSTBUF_LIST *) malloc (sizeof (GSTBUF_LIST)))) {
+      GST_ERROR_OBJECT (bcmdec, "mempool malloc failed ");
+      return FALSE;
+    }
+    memset (gst_queue_element, 0, sizeof (GSTBUF_LIST));
+    bcmdec_put_que_mem_buf (bcmdec, gst_queue_element);
+  }
+  return TRUE;
+}
+
+static gboolean
+bcmdec_release_mem_buf_que_pool (GstBcmDec * bcmdec)
+{
+  GSTBUF_LIST *gst_queue_element;
+  guint i = 0;
+
+  do {
+    gst_queue_element = bcmdec_get_que_mem_buf (bcmdec);
+    if (gst_queue_element) {
+      free (gst_queue_element);
+      i++;
+    }
+  } while (gst_queue_element);
+
+  bcmdec->gst_mem_buf_que_hd = NULL;
+  if (!bcmdec->silent)
+    GST_DEBUG_OBJECT (bcmdec, "mem_buf_que_pool released...  %d", i);
+
+  return TRUE;
+}
+
+static void
+bcmdec_ins_buf (GstBcmDec * bcmdec, GSTBUF_LIST * gst_queue_element)
+{
+  pthread_mutex_lock (&bcmdec->gst_buf_que_lock);
+
+  if (!bcmdec->gst_buf_que_hd) {
+    bcmdec->gst_buf_que_hd = bcmdec->gst_buf_que_tl = gst_queue_element;
+  } else {
+    bcmdec->gst_buf_que_tl->next = gst_queue_element;
+    bcmdec->gst_buf_que_tl = gst_queue_element;
+    gst_queue_element->next = NULL;
+  }
+
+  if (sem_post (&bcmdec->buf_event) == -1)
+    GST_ERROR_OBJECT (bcmdec, "buf sem_post failed");
+  else
+    GST_DEBUG_OBJECT (bcmdec, "buffer inserted and buf_event signalled");
+
+  pthread_mutex_unlock (&bcmdec->gst_buf_que_lock);
+}
+
+static GSTBUF_LIST *
+bcmdec_rem_buf (GstBcmDec * bcmdec)
+{
+  GSTBUF_LIST *temp;
+
+  pthread_mutex_lock (&bcmdec->gst_buf_que_lock);
+
+  if (bcmdec->gst_buf_que_hd == bcmdec->gst_buf_que_tl) {
+    temp = bcmdec->gst_buf_que_hd;
+    bcmdec->gst_buf_que_hd = bcmdec->gst_buf_que_tl = NULL;
+  } else {
+    temp = bcmdec->gst_buf_que_hd;
+    bcmdec->gst_buf_que_hd = temp->next;
+  }
+
+  pthread_mutex_unlock (&bcmdec->gst_buf_que_lock);
+
+  return temp;
+}
+
+static BC_STATUS
+bcmdec_insert_sps_pps (GstBcmDec * bcmdec, GstMapInfo * info)
+{
+  BC_STATUS sts = BC_STS_SUCCESS;
+  guint8 *data = info->data;
+  guint32 data_size = info->size;
+  gint profile;
+  guint nal_size;
+  guint num_sps, num_pps, i;
+
+  bcmdec->codec_params.pps_size = 0;
+
+  profile = (data[1] << 16) | (data[2] << 8) | data[3];
+  GST_DEBUG_OBJECT (bcmdec, "profile %06x", profile);
+
+  bcmdec->codec_params.nal_size_bytes = (data[4] & 0x03) + 1;
+
+  GST_DEBUG_OBJECT (bcmdec, "nal size %d", bcmdec->codec_params.nal_size_bytes);
+
+  num_sps = data[5] & 0x1f;
+  GST_DEBUG_OBJECT (bcmdec, "num sps %d", num_sps);
+
+  data += 6;
+  data_size -= 6;
+
+  for (i = 0; i < num_sps; i++) {
+
+    if (data_size < 2) {
+      if (!bcmdec->silent)
+        GST_DEBUG_OBJECT (bcmdec, "too small 2");
+      return BC_STS_ERROR;
+    }
+
+    nal_size = (data[0] << 8) | data[1];
+    data += 2;
+    data_size -= 2;
+
+    if (data_size < nal_size) {
+      if (!bcmdec->silent)
+        GST_DEBUG_OBJECT (bcmdec, "too small 3");
+      return BC_STS_ERROR;
+    }
+
+    bcmdec->codec_params.sps_pps_buf[0] = 0;
+    bcmdec->codec_params.sps_pps_buf[1] = 0;
+    bcmdec->codec_params.sps_pps_buf[2] = 0;
+    bcmdec->codec_params.sps_pps_buf[3] = 1;
+
+    bcmdec->codec_params.pps_size += 4;
+
+    memcpy (bcmdec->codec_params.sps_pps_buf + bcmdec->codec_params.pps_size,
+        data, nal_size);
+    bcmdec->codec_params.pps_size += nal_size;
+
+    data += nal_size;
+    data_size -= nal_size;
+  }
+
+  if (data_size < 1) {
+    if (!bcmdec->silent)
+      GST_DEBUG_OBJECT (bcmdec, "too small 4");
+    return BC_STS_ERROR;
+  }
+
+  num_pps = data[0];
+  data += 1;
+  data_size -= 1;
+
+  for (i = 0; i < num_pps; i++) {
+
+    if (data_size < 2) {
+      if (!bcmdec->silent)
+        GST_DEBUG_OBJECT (bcmdec, "too small 5");
+      return BC_STS_ERROR;
+    }
+
+    nal_size = (data[0] << 8) | data[1];
+    data += 2;
+    data_size -= 2;
+
+    if (data_size < nal_size) {
+      if (!bcmdec->silent)
+        GST_DEBUG_OBJECT (bcmdec, "too small 6");
+      return BC_STS_ERROR;
+    }
+
+    bcmdec->codec_params.sps_pps_buf[bcmdec->codec_params.pps_size + 0] = 0;
+    bcmdec->codec_params.sps_pps_buf[bcmdec->codec_params.pps_size + 1] = 0;
+    bcmdec->codec_params.sps_pps_buf[bcmdec->codec_params.pps_size + 2] = 0;
+    bcmdec->codec_params.sps_pps_buf[bcmdec->codec_params.pps_size + 3] = 1;
+
+    bcmdec->codec_params.pps_size += 4;
+
+    memcpy (bcmdec->codec_params.sps_pps_buf + bcmdec->codec_params.pps_size,
+        data, nal_size);
+    bcmdec->codec_params.pps_size += nal_size;
+
+    data += nal_size;
+    data_size -= nal_size;
+  }
+
+  GST_DEBUG_OBJECT (bcmdec, "data size at end = %d ", data_size);
+
+  return sts;
+}
+
+static gboolean
+bcmdec_mul_inst_cor (GstBcmDec * bcmdec)
+{
+  struct timespec ts;
+  gint ret = 0;
+  int i = 0;
+
+  if ((intptr_t) g_inst_sts == -1) {
+    GST_ERROR_OBJECT (bcmdec, "mul_inst_cor :shmem ptr invalid");
+    return FALSE;
+  }
+
+  if (g_inst_sts->cur_decode == PLAYBACK) {
+    GST_DEBUG_OBJECT (bcmdec, "mul_inst_cor : ret false %d",
+        g_inst_sts->cur_decode);
+    return FALSE;
+  }
+
+  for (i = 0; i < 15; i++) {
+    ts.tv_sec = time (NULL) + 3;
+    ts.tv_nsec = 0;
+    ret = sem_timedwait (&g_inst_sts->inst_ctrl_event, &ts);
+    if (ret < 0) {
+      if (errno == ETIMEDOUT) {
+        if (g_inst_sts->cur_decode == PLAYBACK) {
+          GST_DEBUG_OBJECT (bcmdec, "mul_inst_cor :playback is set , exit");
+          return FALSE;
+        } else {
+          GST_DEBUG_OBJECT (bcmdec,
+              "mul_inst_cor :wait for thumb nail decode finish");
+          continue;
+        }
+      } else if (errno == EINTR) {
+        return FALSE;
+      }
+    } else {
+      GST_DEBUG_OBJECT (bcmdec, "mul_inst_cor :ctrl_event is given");
+      return TRUE;
+    }
+  }
+  GST_DEBUG_OBJECT (bcmdec, "mul_inst_cor : ret false cur_dec = %d wait = %d",
+      g_inst_sts->cur_decode, g_inst_sts->waiting);
+
+  return FALSE;
+}
+
+static BC_STATUS
+bcmdec_create_shmem (GstBcmDec * bcmdec, int *shmem_id)
+{
+  int shmid = -1;
+  key_t shmkey = BCM_GST_SHMEM_KEY;
+  struct shmid_ds buf;
+
+  if (shmem_id == NULL) {
+    GST_ERROR_OBJECT (bcmdec, "Invalid argument ...");
+    return BC_STS_INSUFF_RES;
+  }
+
+  *shmem_id = shmid;
+
+  //First Try to create it.
+  shmid = shmget (shmkey, 1024, 0644 | IPC_CREAT | IPC_EXCL);
+  if (shmid == -1) {
+    if (errno == EEXIST) {
+      GST_DEBUG_OBJECT (bcmdec, "bcmdec_create_shmem:shmem already exists :%d",
+          errno);
+      shmid = shmget (shmkey, 1024, 0644);
+      if (shmid == -1) {
+        GST_ERROR_OBJECT (bcmdec, "bcmdec_create_shmem:unable to get shmid :%d",
+            errno);
+        return BC_STS_INSUFF_RES;
+      }
+      //we got the shmid, see if any process is alreday attached to it
+      if (shmctl (shmid, IPC_STAT, &buf) == -1) {
+        GST_ERROR_OBJECT (bcmdec, "bcmdec_create_shmem:shmctl failed ...");
+        return BC_STS_ERROR;
+      }
+
+      if (buf.shm_nattch == 0) {
+        sem_destroy (&g_inst_sts->inst_ctrl_event);
+        //No process is currently attached to the shmem seg. go ahead and delete it as its contents are stale.
+        if (shmctl (shmid, IPC_RMID, NULL) != -1)
+          GST_DEBUG_OBJECT (bcmdec,
+              "bcmdec_create_shmem:deleted shmem segment and creating a new one ...");
+        //create a new shmem
+        shmid = shmget (shmkey, 1024, 0644 | IPC_CREAT | IPC_EXCL);
+        if (shmid == -1) {
+          GST_ERROR_OBJECT (bcmdec,
+              "bcmdec_create_shmem:unable to get shmid :%d", errno);
+          return BC_STS_INSUFF_RES;
+        }
+        //attach to it
+        bcmdec_get_shmem (bcmdec, shmid, TRUE);
+
+      } else {
+        //attach to it
+        bcmdec_get_shmem (bcmdec, shmid, FALSE);
+      }
+
+    } else {
+      GST_ERROR_OBJECT (bcmdec, "shmcreate failed with err %d", errno);
+      return BC_STS_ERROR;
+    }
+  } else {
+    //we created just attach to it
+    bcmdec_get_shmem (bcmdec, shmid, TRUE);
+  }
+
+  *shmem_id = shmid;
+
+  return BC_STS_SUCCESS;
+}
+
+static BC_STATUS
+bcmdec_get_shmem (GstBcmDec * bcmdec, int shmid, gboolean newmem)
+{
+  gint ret = 0;
+  g_inst_sts = (GLB_INST_STS *) shmat (shmid, (void *) 0, 0);
+  if ((intptr_t) g_inst_sts == -1) {
+    GST_ERROR_OBJECT (bcmdec, "Unable to open shared memory ...errno = %d",
+        errno);
+    return BC_STS_ERROR;
+  }
+
+  if (newmem) {
+    ret = sem_init (&g_inst_sts->inst_ctrl_event, 5, 1);
+    if (ret != 0) {
+      GST_ERROR_OBJECT (bcmdec, "inst_ctrl_event failed");
+      return BC_STS_ERROR;
+    }
+  }
+
+  return BC_STS_SUCCESS;
+}
+
+static BC_STATUS
+bcmdec_del_shmem (GstBcmDec * bcmdec)
+{
+  int shmid = 0;
+  struct shmid_ds buf;
+
+  //First dettach the shared mem segment
+  if (shmdt (g_inst_sts) == -1)
+    GST_ERROR_OBJECT (bcmdec, "Unable to detach shared memory ...");
+
+  //delete the shared mem segment if there are no other attachments
+  shmid = shmget ((key_t) BCM_GST_SHMEM_KEY, 0, 0);
+  if (shmid == -1) {
+    GST_ERROR_OBJECT (bcmdec, "bcmdec_del_shmem:Unable get shmid ...");
+    return BC_STS_ERROR;
+  }
+
+  if (shmctl (shmid, IPC_STAT, &buf) == -1) {
+    GST_ERROR_OBJECT (bcmdec, "bcmdec_del_shmem:shmctl failed ...");
+    return BC_STS_ERROR;
+  }
+
+  if (buf.shm_nattch == 0) {
+    sem_destroy (&g_inst_sts->inst_ctrl_event);
+    //No process is currently attached to the shmem seg. go ahead and delete it
+    if (shmctl (shmid, IPC_RMID, NULL) != -1) {
+      GST_ERROR_OBJECT (bcmdec, "bcmdec_del_shmem:deleted shmem segment ...");
+      return BC_STS_ERROR;
+    } else {
+      GST_ERROR_OBJECT (bcmdec,
+          "bcmdec_del_shmem:unable to delete shmem segment ...");
+    }
+  }
+
+  return BC_STS_SUCCESS;
+}
+
+// For renderer buffer
+static void
+bcmdec_flush_gstrbuf_queue (GstBcmDec * bcmdec)
+{
+  GSTBUF_LIST *gst_queue_element = NULL;
+
+  while (1) {
+    gst_queue_element = bcmdec_rem_padbuf (bcmdec);
+    if (gst_queue_element) {
+      if (gst_queue_element->gstbuf) {
+        gst_buffer_unref (gst_queue_element->gstbuf);
+        bcmdec_put_que_mem_buf (bcmdec, gst_queue_element);
+      } else {
+        break;
+      }
+    } else {
+      GST_DEBUG_OBJECT (bcmdec, "no gst_queue_element");
+      break;
+    }
+  }
+}
+
+static void *
+bcmdec_process_get_rbuf (void *ctx)
+{
+  GstBcmDec *bcmdec = (GstBcmDec *) ctx;
+  GstFlowReturn ret = GST_FLOW_ERROR;
+  GSTBUF_LIST *gst_queue_element = NULL;
+  gboolean result = FALSE, done = FALSE;
+  GstBuffer *gstbuf = NULL;
+  guint bufSz = 0;
+  gboolean get_buf_start = FALSE;
+  int revent = -1;
+
+  while (1) {
+    revent = sem_trywait (&bcmdec->rbuf_start_event);
+    if (revent == 0) {
+      if (!bcmdec->silent)
+        GST_DEBUG_OBJECT (bcmdec, "got start get buf event ");
+      get_buf_start = TRUE;
+      bcmdec->rbuf_thread_running = TRUE;
+    }
+
+    revent = sem_trywait (&bcmdec->rbuf_stop_event);
+    if (revent == 0) {
+      if (!bcmdec->silent)
+        GST_DEBUG_OBJECT (bcmdec, "quit event set, exit");
+      break;
+    }
+
+    if (!bcmdec->streaming || !get_buf_start) {
+      GST_DEBUG_OBJECT (bcmdec, "SLEEPING in get bufs");
+      usleep (100 * 1000);
+    }
+
+    while (bcmdec->streaming && get_buf_start) {
+      gstbuf = NULL;
+
+      if (!bcmdec->recv_thread && !bcmdec->streaming) {
+        if (!bcmdec->silent)
+          GST_DEBUG_OBJECT (bcmdec, "process get rbuf prepare exiting..");
+        done = TRUE;
+        break;
+      }
+
+      if (bcmdec->gst_padbuf_que_cnt >= GST_RENDERER_BUF_POOL_SZ) {
+        usleep (100 * 1000);    /* we have enought buffers from the renderer */
+        GST_DEBUG_OBJECT (bcmdec, "SLEEPING because we have enough buffers");
+        continue;
+      }
+
+      if (gst_queue_element == NULL)
+        gst_queue_element = bcmdec_get_que_mem_buf (bcmdec);
+
+      if (!gst_queue_element) {
+        if (!bcmdec->silent)
+          GST_DEBUG_OBJECT (bcmdec, "mbuf full == TRUE %u",
+              bcmdec->gst_buf_que_sz);
+
+        usleep (100 * 1000);    // Sleep since we have buffers queued up
+        continue;
+      }
+
+      bufSz =
+          bcmdec->output_params.width * bcmdec->output_params.height * BUF_MULT;
+
+      GST_DEBUG_OBJECT (bcmdec,
+          "process get rbuf gst_pad_alloc_buffer_and_set_caps ....");
+      if (!bcmdec_get_buffer (bcmdec, bufSz, &gstbuf)) {
+        GST_ERROR_OBJECT (bcmdec,
+            "gst_pad_alloc_buffer_and_set_caps failed %d ", ret);
+        usleep (30 * 1000);
+        continue;
+      }
+
+      GST_DEBUG_OBJECT (bcmdec, "Got GST Buf RCnt:%d",
+          bcmdec->gst_padbuf_que_cnt);
+
+      gst_queue_element->gstbuf = gstbuf;
+      bcmdec_ins_padbuf (bcmdec, gst_queue_element);
+      gst_queue_element = NULL;
+
+      usleep (5 * 1000);
+    }
+
+    if (done) {
+      GST_DEBUG_OBJECT (bcmdec, "process get rbuf done ");
+      break;
+    }
+  }
+  bcmdec_flush_gstrbuf_queue (bcmdec);
+  GST_DEBUG_OBJECT (bcmdec, "process get rbuf exiting.. ");
+  pthread_exit ((void *) &result);
+}
+
+static gboolean
+bcmdec_start_get_rbuf_thread (GstBcmDec * bcmdec)
+{
+  gboolean result = TRUE;
+  gint ret = 0;
+  pthread_attr_t thread_attr;
+
+  bcmdec->gst_padbuf_que_hd = bcmdec->gst_padbuf_que_tl = NULL;
+
+  ret = sem_init (&bcmdec->rbuf_ins_event, 0, 0);
+  if (ret != 0) {
+    GST_ERROR_OBJECT (bcmdec, "get rbuf ins event init failed");
+    result = FALSE;
+  }
+
+  ret = sem_init (&bcmdec->rbuf_start_event, 0, 0);
+  if (ret != 0) {
+    GST_ERROR_OBJECT (bcmdec, "get rbuf start event init failed");
+    result = FALSE;
+  }
+
+  ret = sem_init (&bcmdec->rbuf_stop_event, 0, 0);
+  if (ret != 0) {
+    GST_ERROR_OBJECT (bcmdec, "get rbuf stop event init failed");
+    result = FALSE;
+  }
+
+  pthread_attr_init (&thread_attr);
+  pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_JOINABLE);
+  pthread_create (&bcmdec->get_rbuf_thread, &thread_attr,
+      bcmdec_process_get_rbuf, bcmdec);
+  pthread_attr_destroy (&thread_attr);
+
+  if (!bcmdec->get_rbuf_thread) {
+    GST_ERROR_OBJECT (bcmdec, "Failed to create Renderer buffer Thread");
+    result = FALSE;
+  } else {
+    GST_DEBUG_OBJECT (bcmdec, "Success to create Renderer buffer Thread");
+  }
+
+  return result;
+}
+
+// static void bcmdec_put_que_mem_padbuf(GstBcmDec *bcmdec, GSTBUF_LIST *gst_queue_element)
+// {
+//      pthread_mutex_lock(&bcmdec->gst_padbuf_que_lock);
+//
+//      gst_queue_element->next = bcmdec->gst_mem_padbuf_que_hd;
+//      bcmdec->gst_mem_padbuf_que_hd = gst_queue_element;
+//
+//      pthread_mutex_unlock(&bcmdec->gst_padbuf_que_lock);
+// }
+//
+// static GSTBUF_LIST * bcmdec_get_que_mem_padbuf(GstBcmDec *bcmdec)
+// {
+//      GSTBUF_LIST *gst_queue_element;
+//
+//      pthread_mutex_lock(&bcmdec->gst_padbuf_que_lock);
+//
+//      gst_queue_element = bcmdec->gst_mem_padbuf_que_hd;
+//      if (gst_queue_element !=NULL)
+//              bcmdec->gst_mem_padbuf_que_hd = bcmdec->gst_mem_padbuf_que_hd->next;
+//
+//      pthread_mutex_unlock(&bcmdec->gst_padbuf_que_lock);
+//
+//      return gst_queue_element;
+// }
+//
+// static gboolean bcmdec_alloc_mem_rbuf_que_pool(GstBcmDec *bcmdec)
+// {
+//      GSTBUF_LIST *gst_queue_element;
+//      guint i;
+//
+//      bcmdec->gst_mem_padbuf_que_hd = NULL;
+//      for (i = 1; i < bcmdec->gst_padbuf_que_sz; i++) {
+//              gst_queue_element = (GSTBUF_LIST *)malloc(sizeof(GSTBUF_LIST));
+//              if (!gst_queue_element) {
+//                      GST_ERROR_OBJECT(bcmdec, "mem_rbuf_que_pool malloc failed ");
+//                      return FALSE;
+//              }
+//              memset(gst_queue_element, 0, sizeof(GSTBUF_LIST));
+//              bcmdec_put_que_mem_padbuf(bcmdec, gst_queue_element);
+//      }
+//
+//      return TRUE;
+// }
+//
+// static gboolean bcmdec_release_mem_rbuf_que_pool(GstBcmDec *bcmdec)
+// {
+//      GSTBUF_LIST *gst_queue_element;
+//      guint i = 0;
+//
+//      do {
+//              gst_queue_element = bcmdec_get_que_mem_padbuf(bcmdec);
+//              if (gst_queue_element) {
+//                      free(gst_queue_element);
+//                      i++;
+//              }
+//      } while (gst_queue_element);
+//
+//      bcmdec->gst_mem_padbuf_que_hd = NULL;
+//      if (!bcmdec->silent)
+//              GST_DEBUG_OBJECT(bcmdec, "rend_rbuf_que_pool released... %d", i);
+//
+//      return TRUE;
+// }
+
+static void
+bcmdec_ins_padbuf (GstBcmDec * bcmdec, GSTBUF_LIST * gst_queue_element)
+{
+  pthread_mutex_lock (&bcmdec->gst_padbuf_que_lock);
+
+  if (!bcmdec->gst_padbuf_que_hd) {
+    bcmdec->gst_padbuf_que_hd = bcmdec->gst_padbuf_que_tl = gst_queue_element;
+  } else {
+    bcmdec->gst_padbuf_que_tl->next = gst_queue_element;
+    bcmdec->gst_padbuf_que_tl = gst_queue_element;
+    gst_queue_element->next = NULL;
+  }
+
+  bcmdec->gst_padbuf_que_cnt++;
+  GST_DEBUG_OBJECT (bcmdec, "Inc rbuf:%d", bcmdec->gst_padbuf_que_cnt);
+
+  if (sem_post (&bcmdec->rbuf_ins_event) == -1)
+    GST_ERROR_OBJECT (bcmdec, "rbuf sem_post failed");
+
+  pthread_mutex_unlock (&bcmdec->gst_padbuf_que_lock);
+}
+
+static GSTBUF_LIST *
+bcmdec_rem_padbuf (GstBcmDec * bcmdec)
+{
+  GSTBUF_LIST *temp;
+
+  pthread_mutex_lock (&bcmdec->gst_padbuf_que_lock);
+
+  if (bcmdec->gst_padbuf_que_hd == bcmdec->gst_padbuf_que_tl) {
+    temp = bcmdec->gst_padbuf_que_hd;
+    bcmdec->gst_padbuf_que_hd = bcmdec->gst_padbuf_que_tl = NULL;
+  } else {
+    temp = bcmdec->gst_padbuf_que_hd;
+    bcmdec->gst_padbuf_que_hd = temp->next;
+  }
+
+  if (temp)
+    bcmdec->gst_padbuf_que_cnt--;
+
+  GST_DEBUG_OBJECT (bcmdec, "Dec rbuf:%d", bcmdec->gst_padbuf_que_cnt);
+
+  pthread_mutex_unlock (&bcmdec->gst_padbuf_que_lock);
+
+  return temp;
+}
+
+// End of renderer buffer
+
+/*
+ * entry point to initialize the plug-in
+ * initialize the plug-in itself
+ * register the element factories and other features
+ */
+static gboolean
+plugin_init (GstPlugin * bcmdec)
+{
+  /*
+   * debug category for fltering log messages
+   */
+  GST_DEBUG_CATEGORY_INIT (gst_bcm_dec_debug, "bcmdec", 0,
+      "Broadcom video decoder");
+
+  return gst_element_register (bcmdec, "bcmdec", GST_BCM_DEC_RANK,
+      GST_TYPE_BCM_DEC);
+}
+
+/* gstreamer looks for this structure to register bcmdec */
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, bcmdec,
+    "Video decoder", plugin_init, VERSION, "LGPL", "bcmdec",
+    "http://broadcom.com/")
diff --git a/ext/bcmdec/gstbcmdec.h b/ext/bcmdec/gstbcmdec.h
new file mode 100644
index 0000000..adeda1e
--- /dev/null
+++ b/ext/bcmdec/gstbcmdec.h
@@ -0,0 +1,356 @@
+ /********************************************************************
+ * Copyright(c) 2008 Broadcom Corporation.
+ *
+ *  Name: gstbcmdec.h
+ *
+ *  Description: Broadcom 70012 Decoder plugin header
+ *
+ *  AU
+ *
+ *  HISTORY:
+ *
+ *******************************************************************
+ *
+ * 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.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ *******************************************************************/
+#ifndef __GST_BCM_DEC_H__
+#define __GST_BCM_DEC_H__
+
+
+#define	GST_BCM_DEC_RANK	0xffff
+
+#define CLOCK_BASE 9LL
+#define CLOC_FREQ_CLOC_BASE * 10000
+
+#define GST_BUF_LIST_POOL_SZ  100;
+
+#define GST_RENDERER_BUF_POOL_SZ 20
+
+#define MPEGTIME_TO_GSTTIME(time) ((time) * (GST_MSECOND/10)) / CLOCK_BASE)
+
+#define GSTIME_TO_MPEGTIME(time) (((time) * CLOCK_BASE) / (GST_MSECOND)/10))
+
+const gint64 UNITS = 1000000000;
+
+#define BRCM_START_CODE_SIZE 4
+
+//VC1 prefix 000001
+#define VC1_FRM_SUFFIX	0x0D
+#define VC1_SEQ_SUFFIX	0x0F
+
+//VC1 SM Profile prefix 000001
+#define VC1_SM_FRM_SUFFIX	0xE0
+
+//Check WMV SP/MP PES Payload for PTS Info
+//#define VC1_SM_MAGIC_WORD     0x5A5A5A5A
+//#define VC1_SM_PTS_INFO_START_CODE    0xBD
+
+//MPEG2 prefix 000001
+#define	MPEG2_FRM_SUFFIX 0x00
+#define	MPEG2_SEQ_SUFFIX 0xB3
+
+#define PAUSE_THRESHOLD 16
+#define RESUME_THRESHOLD 8
+#define	SPS_PPS_SIZE 1000
+
+#define BCM_GST_SHMEM_KEY 0xDEADBEEF
+#define	THUMBNAIL_FRAMES 60
+
+typedef enum
+{
+  H264 = 0,
+  MPEG2,
+  VC1
+} VIDFOMATS;
+
+typedef enum
+{
+  NV12 = 0,
+  YUY2,
+  UYVY,
+  YV12
+} CLRSPACE;
+
+typedef struct
+{
+  guint width;
+  guint height;
+  guint8 clr_space;
+  gdouble framerate;
+  guint8 aspectratio_x;
+  guint8 aspectratio_y;
+  guint32 y_size;
+  guint32 uv_size;
+  guint8 stride;
+
+} OUTPARAMS;
+
+typedef struct
+{
+  guint8 *sps_pps_buf;
+  guint32 pps_size;
+  gboolean inside_buffer;
+  guint32 consumed_offset;
+  guint32 strtcode_offset;
+  guint32 nal_sz;
+  guint8 nal_size_bytes;
+} CODEC_PARAMS;
+
+
+
+typedef struct _GSTBUF_LIST
+{
+  GstBuffer *gstbuf;
+  struct _GSTBUF_LIST *next;
+} GSTBUF_LIST;
+
+#define MAX_ADV_PROF_SEQ_HDR_SZ  		50
+
+typedef enum
+{
+  UNKNOWN = 0,
+  THUMBNAIL = 1,
+  PLAYBACK = 2,
+} CURDECODE;
+
+typedef struct
+{
+  guint rendered_frames;
+  gboolean waiting;
+  CURDECODE cur_decode;
+  sem_t inst_ctrl_event;
+} GLB_INST_STS;
+
+
+G_BEGIN_DECLS
+#define GST_TYPE_BCM_DEC \
+  (gst_bcm_dec_get_type())
+#define GST_BCM_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BCM_DEC,GstBcmDec))
+#define GST_BCM_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BCM_DEC,GstBcmDecClass))
+#define GST_IS_BCM_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BCM_DEC))
+#define GST_IS_BCM_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BCM_DEC))
+typedef struct _GstBcmDec GstBcmDec;
+typedef struct _GstBcmDecClass GstBcmDecClass;
+
+
+struct _GstBcmDec
+{
+  GstElement element;
+  GstPad *sinkpad, *srcpad;
+  gboolean silent;
+  void *hdevice;
+  gboolean dec_ready;
+  gboolean streaming;
+  gboolean feos;
+  GMutex *mPlayLock;
+  BC_MEDIA_SUBTYPE input_format;
+  OUTPARAMS output_params;
+  pthread_t recv_thread;
+  sem_t play_event;
+  sem_t quit_event;
+  BcmDecIF decif;
+  Parse parse;
+  BC_PIC_INFO_BLOCK pic_info;
+  gboolean format_reset;
+  gboolean interlace;
+  GstClockTime base_time;
+  FILE *fhnd;
+  gboolean play_pending;
+  GstEvent *ev_eos;
+  GSTBUF_LIST *gst_buf_que_hd;
+  GSTBUF_LIST *gst_buf_que_tl;
+  pthread_mutex_t gst_buf_que_lock;
+  guint gst_que_cnt;
+  pthread_t push_thread;
+  gboolean last_picture_set;
+  sem_t buf_event;
+  guint gst_buf_que_sz;
+  GSTBUF_LIST *gst_mem_buf_que_hd;
+
+  gdouble input_framerate;
+  guint32 prev_pic;
+  gboolean paused;
+  gboolean insert_start_code;
+
+  CODEC_PARAMS codec_params;
+  gboolean sec_field;
+  guint8 input_par_x;
+  guint8 input_par_y;
+
+  gboolean flushing;
+  sem_t push_stop_event;
+  sem_t push_start_event;
+  sem_t recv_stop_event;
+  guint ses_nbr;
+  gboolean insert_pps;
+  gboolean ses_change;
+  gboolean push_exit;
+  pthread_mutex_t fn_lock;
+  gboolean suspend_mode;
+  GstClock *gst_clock;
+  guint32 rpt_pic_cnt;
+
+  gboolean enable_spes;
+  guint8 *dest_buf;
+  guint32 spes_frame_cnt;
+  GstClockTime spes_frm_time;
+  gboolean catchup_on;
+  GstClockTime last_spes_time;
+  GstClockTime last_output_spes_time;
+  GstClockTime frame_time;
+  GstClockTime base_clock_time;
+  GstClockTime prev_clock_time;
+  GstClockTime cur_stream_time;
+  guint8 proc_in_flags;
+
+  gint frame_width;             /*The value from Demux used for WMV9 or VC-1 SP/MP */
+  gint frame_height;            /*The value from Demux used for WMV9 or VC-1 SP/MP */
+
+  GSTBUF_LIST *gst_padbuf_que_hd;
+  GSTBUF_LIST *gst_padbuf_que_tl;
+  pthread_mutex_t gst_padbuf_que_lock;
+  guint gst_padbuf_que_cnt;
+  pthread_t get_rbuf_thread;
+  sem_t rbuf_start_event;
+  sem_t rbuf_stop_event;
+  sem_t rbuf_ins_event;
+  guint gst_padbuf_que_sz;
+  GSTBUF_LIST *gst_mem_padbuf_que_hd;
+  gboolean rbuf_thread_running;
+};
+
+struct _GstBcmDecClass
+{
+  GstElementClass parent_class;
+};
+
+GType gst_bcm_dec_get_type (void);
+
+static void gst_bcm_dec_base_init (gpointer gclass);
+
+static void gst_bcm_dec_finalize (GObject * object);
+
+static GstFlowReturn
+gst_bcm_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer);
+
+static GstStateChangeReturn
+gst_bcm_dec_change_state (GstElement * element, GstStateChange transition);
+
+static gboolean gst_bcm_dec_sink_set_caps (GstPad * pad, GstCaps * caps);
+
+static gboolean
+gst_bcm_dec_src_event (GstPad * pad, GstObject * parent, GstEvent * event);
+
+static gboolean
+gst_bcm_dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event);
+
+static void
+gst_bcm_dec_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+
+static void
+gst_bcm_dec_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static gboolean bcmdec_negotiate_format (GstBcmDec * bcmdec);
+
+static void bcmdec_reset (GstBcmDec * bcmdec);
+
+static gboolean
+bcmdec_get_buffer (GstBcmDec * bcmdec, gint size, GstBuffer ** obuf);
+
+static void *bcmdec_process_output (void *ctx);
+
+static void
+bcmdec_init_procout (GstBcmDec * filter, BC_DTS_PROC_OUT * pout, guint8 * buf);
+
+static void bcmdec_set_framerate (GstBcmDec * filter, guint32 resolution);
+
+static gboolean
+bcmdec_format_change (GstBcmDec * filter, BC_PIC_INFO_BLOCK * pic_info);
+
+static BC_STATUS gst_bcm_dec_cleanup (GstBcmDec * filter);
+
+static gboolean bcmdec_start_recv_thread (GstBcmDec * bcmdec);
+
+static GstClockTime
+bcmdec_get_time_stamp (GstBcmDec * filter, guint32 pic_no,
+    GstClockTime spes_time);
+
+static gboolean bcmdec_process_play (GstBcmDec * filter);
+
+static gboolean bcmdec_alloc_mem_buf_que_pool (GstBcmDec * filter);
+
+static gboolean bcmdec_release_mem_buf_que_pool (GstBcmDec * filter);
+
+static void
+bcmdec_put_que_mem_buf (GstBcmDec * filter, GSTBUF_LIST * gst_queue_element);
+
+static GSTBUF_LIST *bcmdec_get_que_mem_buf (GstBcmDec * filter);
+
+static void
+bcmdec_ins_buf (GstBcmDec * filter, GSTBUF_LIST * gst_queue_element);
+
+static GSTBUF_LIST *bcmdec_rem_buf (GstBcmDec * filter);
+
+static void *bcmdec_process_push (void *ctx);
+
+static gboolean bcmdec_start_push_thread (GstBcmDec * bcmdec);
+
+//static BC_STATUS
+//bcmdec_insert_startcode(GstBcmDec* filter,GstBuffer* gstbuf, guint8* dest_buf,guint32* sz);
+
+static BC_STATUS
+bcmdec_insert_sps_pps (GstBcmDec * filter, GstMapInfo * gstbuf);
+
+static void
+bcmdec_set_aspect_ratio (GstBcmDec * filter, BC_PIC_INFO_BLOCK * pic_info);
+
+static void bcmdec_process_flush_start (GstBcmDec * filter);
+
+static void bcmdec_process_flush_stop (GstBcmDec * filter);
+
+static gboolean bcmdec_mul_inst_cor (GstBcmDec * filter);
+
+static BC_STATUS bcmdec_create_shmem (GstBcmDec * filter, int *shmem_id);
+
+static BC_STATUS
+bcmdec_get_shmem (GstBcmDec * filter, int shmid, gboolean newsh);
+
+static BC_STATUS bcmdec_del_shmem (GstBcmDec * filter);
+
+static gboolean bcmdec_start_get_rbuf_thread (GstBcmDec * bcmdec);
+
+// static gboolean
+// bcmdec_alloc_mem_padbuf_que_pool(GstBcmDec *filter);
+//
+// static gboolean
+// bcmdec_release_mem_padbuf_que_pool(GstBcmDec *filter);
+
+// static void
+// bcmdec_put_que_mem_padbuf(GstBcmDec *filter,GSTBUF_LIST *gst_queue_element);
+//
+// static GSTBUF_LIST*
+// bcmdec_get_que_mem_padbuf(GstBcmDec *filter);
+
+static void
+bcmdec_ins_padbuf (GstBcmDec * filter, GSTBUF_LIST * gst_queue_element);
+
+static GSTBUF_LIST *bcmdec_rem_padbuf (GstBcmDec * filter);
+
+G_END_DECLS
+#endif /* __GST_BCM_DEC_H__ */
diff --git a/ext/bcmdec/parse.c b/ext/bcmdec/parse.c
new file mode 100644
index 0000000..b2853f5
--- /dev/null
+++ b/ext/bcmdec/parse.c
@@ -0,0 +1,309 @@
+ /*******************************************************************
+ *
+ * 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.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ *******************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <getopt.h>
+#include <errno.h>
+#include <glib.h>
+#include <gst/gst.h>
+#include "bc_dts_defs.h"
+#include "bc_dts_types.h"
+#include "parse.h"
+
+inline gint NextBit (SymbInt *);
+
+void
+parse_init (Parse * parse)
+{
+  parse->bIsFirstByteStreamNALU = TRUE;
+}
+
+gboolean
+parse_find_strt_code (Parse * parse, guint8 input_format, guint8 * in_buffer,
+    guint32 size, guint32 * poffset)
+{
+  guint32 i = 0;
+  guint8 Suffix1 = 0;
+  guint8 Suffix2 = 0;
+
+  if (input_format == BC_VID_ALGO_VC1) {
+    Suffix1 = VC1_FRM_SUFFIX;
+    Suffix2 = VC1_SEQ_SUFFIX;
+  } else if (input_format == BC_VID_ALGO_MPEG2) {
+    Suffix1 = MPEG2_FRM_SUFFIX;
+    Suffix2 = MPEG2_SEQ_SUFFIX;
+  }
+  /* For VC-1 SP/MP */
+  else if (input_format == BC_VID_ALGO_VC1MP) {
+    Suffix1 = VC1_SM_FRM_SUFFIX;
+  }
+
+  if (input_format == BC_VID_ALGO_H264) {
+    int nNalType = 0;
+    uint32_t ulPos = 0;
+    nNalType = parseAVC (parse, in_buffer, size, &ulPos);
+    if ((nNalType == NALU_TYPE_SEI) || (nNalType == NALU_TYPE_PPS) ||
+        (nNalType == NALU_TYPE_SPS)) {
+      *poffset = ulPos;
+      return TRUE;
+    } else if ((nNalType == NALU_TYPE_SLICE) | (nNalType == NALU_TYPE_IDR)) {
+      *poffset = 0;
+      return TRUE;
+    }
+  } else {                      /* VC1, MPEG2 */
+    while (i < size) {
+      if ((*(in_buffer + i) == Suffix1) || (*(in_buffer + i) == Suffix2)) {
+        if (i >= 3) {
+          if ((*(in_buffer + (i - 3)) == 0x00) &&
+              (*(in_buffer + (i - 2)) == 0x00) &&
+              (*(in_buffer + (i - 1)) == 0x01)) {
+            *poffset = i - 3;
+            return TRUE;
+          }
+        }
+      }
+      i++;
+    }
+  }
+
+  return FALSE;
+}
+
+static gint
+FindBSStartCode (guint8 * Buf, gint ZerosInStartcode)
+{
+  gboolean bStartCode = TRUE;
+  gint i;
+
+  for (i = 0; i < ZerosInStartcode; i++)
+    if (Buf[i] != 0)
+      bStartCode = FALSE;
+
+  if (Buf[i] != 1)
+    bStartCode = FALSE;
+
+  return bStartCode;
+}
+
+gint
+GetNaluType (Parse * parse, guint8 * pInputBuf, guint32 ulSize, NALU_t * pNalu)
+{
+  gint b20sInSC, b30sInSC;
+  gint bStartCodeFound, Rewind;
+  gint nLeadingZero8BitsCount = 0, TrailingZero8Bits = 0;
+  guint32 Pos = 0;
+
+  while (Pos <= ulSize) {
+    if ((pInputBuf[Pos++]) == 0)
+      continue;
+    else
+      break;
+  }
+
+  if (pInputBuf[Pos - 1] != 1)
+    return -1;
+
+  if (Pos < 3) {
+    return -1;
+  } else if (Pos == 3) {
+    pNalu->StartcodePrefixLen = 3;
+    nLeadingZero8BitsCount = 0;
+  } else {
+    nLeadingZero8BitsCount = Pos - 4;
+    pNalu->StartcodePrefixLen = 4;
+  }
+
+  /*
+   * the 1st byte stream NAL unit can has nLeadingZero8BitsCount, but subsequent
+   * ones are not allowed to contain it since these zeros (if any) are considered
+   * trailing_zero_8bits of the previous byte stream NAL unit.
+   */
+  if (!parse->bIsFirstByteStreamNALU && nLeadingZero8BitsCount > 0)
+    return -1;
+
+  parse->bIsFirstByteStreamNALU = FALSE;
+
+  bStartCodeFound = 0;
+  b20sInSC = 0;
+  b30sInSC = 0;
+
+  while ((!bStartCodeFound) && (Pos < ulSize)) {
+    Pos++;
+    if (Pos > ulSize)
+      printf ("GetNaluType : Pos > size = %d\n", ulSize);
+
+    b30sInSC = FindBSStartCode ((pInputBuf + Pos - 4), 3);
+    if (b30sInSC != 1)
+      b20sInSC = FindBSStartCode ((pInputBuf + Pos - 3), 2);
+    bStartCodeFound = (b20sInSC || b30sInSC);
+  }
+
+  Rewind = 0;
+#if 0
+  if (!bStartCodeFound) {
+    //even if next start code is not found pprocess this NAL.
+    return -1;
+  }
+#endif
+
+  if (bStartCodeFound) {
+    //Count the trailing_zero_8bits
+    //TrailingZero8Bits is present only for start code 00 00 00 01
+    if (b30sInSC) {
+      while (pInputBuf[Pos - 5 - TrailingZero8Bits] == 0)
+        TrailingZero8Bits++;
+    }
+    // Here, we have found another start code (and read length of startcode bytes more than we should
+    // have.  Hence, go back in the file
+
+    if (b30sInSC)
+      Rewind = -4;
+    else if (b20sInSC)
+      Rewind = -3;
+  }
+  // Here the leading zeros(if any), Start code, the complete NALU, trailing zeros(if any)
+  // until the  next start code .
+  // Total size traversed is Pos, Pos+rewind are the number of bytes excluding the next
+  // start code, and (Pos+rewind)-StartcodePrefixLen-LeadingZero8BitsCount-TrailingZero8Bits
+  // is the size of the NALU.
+
+  pNalu->Len =
+      (Pos + Rewind) - pNalu->StartcodePrefixLen - nLeadingZero8BitsCount -
+      TrailingZero8Bits;
+
+  pNalu->NalUnitType =
+      (pInputBuf[nLeadingZero8BitsCount + pNalu->StartcodePrefixLen]) & 0x1f;
+
+  return (Pos + Rewind);
+}
+
+gint
+parseAVC (Parse * parse, guint8 * pInputBuf, guint32 ulSize, guint32 * Offset)
+{
+  NALU_t Nalu;
+  gint ret = 0;
+  guint32 Pos = 0;
+  gboolean bResult = FALSE;
+
+  while (1) {
+    ret = GetNaluType (parse, pInputBuf + Pos, ulSize - Pos, &Nalu);
+    if (ret <= 0)
+      return -1;
+
+    Pos += ret;
+
+    switch (Nalu.NalUnitType) {
+      case NALU_TYPE_SLICE:
+      case NALU_TYPE_IDR:
+        bResult = TRUE;
+        break;
+      case NALU_TYPE_SEI:
+      case NALU_TYPE_PPS:
+      case NALU_TYPE_SPS:
+        bResult = TRUE;
+        break;
+      case NALU_TYPE_DPA:
+      case NALU_TYPE_DPC:
+      case NALU_TYPE_AUD:
+      case NALU_TYPE_EOSEQ:
+      case NALU_TYPE_EOSTREAM:
+      case NALU_TYPE_FILL:
+      default:
+        break;
+    }
+
+    if (bResult) {
+      *Offset = Pos;
+      break;
+    }
+  }
+
+  return Nalu.NalUnitType;
+}
+
+gboolean
+SiBuffer (SymbInt * simb_int, guint8 * pInputBuffer, guint32 ulSize)
+{
+  simb_int->m_pCurrent = simb_int->m_pInputBuffer = (guint8 *) pInputBuffer;
+  simb_int->m_nSize = ulSize;
+  simb_int->m_pInputBufferEnd = simb_int->m_pInputBuffer + ulSize;
+  simb_int->m_nUsed = 1;
+  simb_int->m_ulOffset = 0;
+  simb_int->m_ulMask = 0x80;
+
+  return TRUE;
+}
+
+gboolean
+SiUe (SymbInt * simb_int, guint32 * pCode)
+{
+  guint32 ulSuffix;
+  int nLeadingZeros;
+  int nBit;
+
+  nLeadingZeros = -1;
+  for (nBit = 0; nBit == 0; nLeadingZeros++) {
+    nBit = NextBit (simb_int);
+    if (simb_int->m_nUsed >= simb_int->m_nSize)
+      return FALSE;
+  }
+
+  *pCode = (1 << nLeadingZeros) - 1;
+
+  ulSuffix = 0;
+  while (nLeadingZeros-- > 0) {
+    ulSuffix = (ulSuffix << 1) | NextBit (simb_int);
+    if (simb_int->m_nUsed >= simb_int->m_nSize)
+      return FALSE;
+  }
+  *pCode += ulSuffix;
+
+  return TRUE;
+}
+
+inline gint
+NextBit (SymbInt * simb_int)
+{
+  int nBit;
+
+  nBit = (simb_int->m_pCurrent[0] & simb_int->m_ulMask) ? 1 : 0;
+
+  if ((simb_int->m_ulMask >>= 1) == 0) {
+    simb_int->m_ulMask = 0x80;
+
+    if (simb_int->m_nUsed == simb_int->m_nSize)
+      simb_int->m_pCurrent = simb_int->m_pInputBuffer;  //reset look again
+    else {
+      if (++simb_int->m_pCurrent == simb_int->m_pInputBufferEnd)
+        simb_int->m_pCurrent = simb_int->m_pInputBuffer;
+      simb_int->m_nUsed++;
+    }
+  }
+  simb_int->m_ulOffset++;
+
+  return nBit;
+}
+
+guint32
+SiOffset (SymbInt * simb_int)
+{
+  return simb_int->m_ulOffset;
+}
diff --git a/ext/bcmdec/parse.h b/ext/bcmdec/parse.h
new file mode 100644
index 0000000..adbb37c
--- /dev/null
+++ b/ext/bcmdec/parse.h
@@ -0,0 +1,107 @@
+/*******************************************************************
+ *
+ * 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.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ *******************************************************************/
+#ifndef CPARSE
+#define CPARSE
+
+//VC1 prefix 000001
+#define VC1_FRM_SUFFIX	0x0D
+#define VC1_SEQ_SUFFIX	0x0F
+
+//VC1 SM Profile prefix 000001
+#define VC1_SM_FRM_SUFFIX	0xE0
+
+//Check WMV SP/MP PES Payload for PTS Info
+#define VC1_SM_MAGIC_WORD	0x5A5A5A5A
+#define VC1_SM_PTS_INFO_START_CODE	0xBD
+
+//MPEG2 prefix 000001
+#define	MPEG2_FRM_SUFFIX 0x00
+#define	MPEG2_SEQ_SUFFIX 0xB3
+
+typedef enum
+{
+  P_SLICE = 0,
+  B_SLICE,
+  I_SLICE,
+  SP_SLICE,
+  SI_SLICE
+} SliceType;
+
+
+typedef enum
+{
+  NALU_TYPE_SLICE = 1,
+  NALU_TYPE_DPA,
+  NALU_TYPE_DPB,
+  NALU_TYPE_DPC,
+  NALU_TYPE_IDR,
+  NALU_TYPE_SEI,
+  NALU_TYPE_SPS,
+  NALU_TYPE_PPS,
+  NALU_TYPE_AUD,
+  NALU_TYPE_EOSEQ,
+  NALU_TYPE_EOSTREAM,
+  NALU_TYPE_FILL
+} NALuType;
+
+typedef struct
+{
+  gint StartcodePrefixLen;      //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested)
+  guint Len;                    //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU)
+  guint MaxSize;                //! Nal Unit Buffer size
+  gint NalUnitType;             //! NALU_TYPE_xxxx
+  gint ForbiddenBit;            //! should be always FALSE
+  guint8 *pNalBuf;
+} NALU_t;
+
+typedef struct
+{
+  guint8 *m_pInputBuffer;
+  guint8 *m_pInputBufferEnd;
+  guint8 *m_pCurrent;
+  guint32 m_ulMask;
+  guint32 m_ulOffset;
+  gint m_nSize;
+  gint m_nUsed;
+  guint32 m_ulZero;
+} SymbInt;
+
+typedef struct
+{
+  gboolean bIsFirstByteStreamNALU;
+  SymbInt symb_int;
+
+} Parse;
+
+
+void parse_init (Parse * parse);
+
+gint
+parseAVC (Parse * parse, guint8 * pInputBuf, guint32 ulSize, guint32 * Offset);
+
+gboolean
+parse_find_strt_code (Parse * parse, guint8 input_format, guint8 * in_buffer,
+    guint32 size, guint32 * poffset);
+
+gint
+GetNaluType (Parse * parse, guint8 * pInputBuf, guint32 ulSize, NALU_t * pNalu);
+
+gboolean SiBuffer (SymbInt * simb_int, guint8 * pInputBuffer, guint32 ulSize);
+
+gboolean SiUe (SymbInt * simb_int, guint32 * pCode);
+
+guint32 SiOffset (SymbInt *);
+
+#endif
diff --git a/ext/bcmdec/version.h b/ext/bcmdec/version.h
new file mode 100644
index 0000000..f7359ed
--- /dev/null
+++ b/ext/bcmdec/version.h
@@ -0,0 +1,203 @@
+/********************************************************************
+* Copyright(c) 2006 Broadcom Corporation.
+*
+*  Name: version.h
+*
+*  Description: Version numbering for the driver use.
+*
+*  AU
+*
+*  HISTORY:
+*
+*******************************************************************
+*
+* 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.
+*
+* 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, see <http://www.gnu.org/licenses/>.
+*
+*******************************************************************/
+
+#ifndef _BC_DTS_VERSION_
+#define _BC_DTS_VERSION_
+//
+// The version format that we are adopting is
+// MajorVersion.MinorVersion.Revision
+// This will be the same for all the components.
+//
+//
+#define STRINGIFY_VERSION(MAJ,MIN,REV) STRINGIFIED_VERSION(MAJ,MIN,REV)
+#define STRINGIFIED_VERSION(MAJ,MIN,REV) #MAJ "." #MIN "." #REV
+
+#define STRINGIFY_VERSION_W(MAJ,MIN,REV) STRINGIFIED_VERSION_W(MAJ,MIN,REV)
+#define STRINGIFIED_VERSION_W(MAJ,MIN,REV) #MAJ "." #MIN "." #REV
+
+//
+//  Product Version number is:
+//  x.y.z.a
+//
+//  x = Major release.      1 = Dozer, 2 = Dozer + Link
+//  y = Minor release.      Should increase +1 per "real" release.
+//  z = Branch release.     0 for main branch.  This is +1 per branch release.
+//  a = Build number        +1 per candidate release.  Reset to 0 every "real" release.
+//
+//
+// Enabling Check-In rules enforcement 08092007
+//
+#define INVALID_VERSION             0xFFFF
+
+/*========================== Common For All Components =================================*/
+#define RC_COMPANY_NAME             "Broadcom Corporation\0"
+#define RC_PRODUCT_VERSION          "2.7.0.25"
+#define RC_W_PRODUCT_VERSION        L"2.7.0.25"
+#define RC_PRODUCT_NAME             "Broadcom Video Decoder\0"
+#define RC_COMMENTS                 "Broadcom BCM70010/BCM70012 Controller\0"
+#define RC_COPYRIGHT                "Copyright(c) 2007 Broadcom Corporation"
+#define RC_PRIVATE_BUILD            "Broadcom Corp. Private\0"
+#define RC_LEGAL_TRADEMARKS         " \0"
+#define BRCM_MAJOR_VERSION          2
+
+
+/*========================== WDM Driver =================================*/
+
+/*
+ * Version number scheme for driver DVMJVer.DVMNVer.DVRev.UNMODIFIED
+ * Where DVMJVer = DRIVER_MAJOR_VERSION
+ * DVMNVer = DRIVER_MINOR_VERSION
+ * DVRev = DRIVER_REVISION
+ * UNMODIFIED = This is for Compatibility with windows INF file version scheme.
+ */
+
+#define RC_FILE_DESCRIPTION         "Broadcom BCM70010/BCM70012 Driver\0"
+#define RC_INTERNAL_NAME            ""
+#define RC_ORIGINAL_NAME            RC_INTERNAL_NAME
+#define RC_SPECIAL_BUILD            ""
+
+#define DRIVER_MAJOR_VERSION        BRCM_MAJOR_VERSION
+#define DRIVER_MINOR_VERSION        31
+#define DRIVER_REVISION             0
+
+#define RC_FILE_VERSION             STRINGIFY_VERSION(DRIVER_MAJOR_VERSION,DRIVER_MINOR_VERSION,DRIVER_REVISION) ".0"
+
+/*======================= Device Interface Library ========================*/
+#define DIL_MAJOR_VERSION           BRCM_MAJOR_VERSION
+#define DIL_MINOR_VERSION           26
+#define DIL_REVISION                0
+
+#define DIL_RC_FILE_VERSION         STRINGIFY_VERSION(DIL_MAJOR_VERSION,DIL_MINOR_VERSION,DIL_REVISION)
+
+/*========================== Direct Show Filter ==============================*/
+#define DFILTER_MAJOR_VERSION       BRCM_MAJOR_VERSION
+#define DFILTER_MINOR_VERSION       26
+#define DFILTER_REVISION            0
+
+#define DFILTER_RC_FILE_VERSION     STRINGIFY_VERSION(DFILTER_MAJOR_VERSION,DFILTER_MINOR_VERSION,DFILTER_REVISION)
+
+/*========================== Direct Show NS Filter ==============================*/
+#define NS_DFILTER_MAJOR_VERSION    BRCM_MAJOR_VERSION
+#define NS_DFILTER_MINOR_VERSION    41
+#define NS_DFILTER_REVISION         0
+
+#define NS_DFILTER_RC_FILE_VERSION  STRINGIFY_VERSION(NS_DFILTER_MAJOR_VERSION,NS_DFILTER_MINOR_VERSION,NS_DFILTER_REVISION)
+
+/*========================== deconf utility ==============================*/
+#define DECONF_MAJOR_VERSION        BRCM_MAJOR_VERSION
+#define DECONF_MINOR_VERSION        10
+#define DECONF_REVISION             0
+
+/*========================== MP-4 Demux Filter ==============================*/
+#define MP4DEMUX_MAJOR_VERSION      BRCM_MAJOR_VERSION
+#define MP4DEMUX_MINOR_VERSION      7
+#define MP4DEMUX_REVISION           0
+
+#define MP4DEMUX_RC_FILE_VERSION    STRINGIFY_VERSION(MP4DEMUX_MAJOR_VERSION,MP4DEMUX_MINOR_VERSION,MP4DEMUX_REVISION)
+
+/*========================== MFT Decoder ==============================*/
+#define MFTDECODER_MAJOR_VERSION    BRCM_MAJOR_VERSION
+#define MFTDECODER_MINOR_VERSION    4
+#define MFTDECODER_REVISION         0
+
+#define MFTDECODER_RC_FILE_VERSION  STRINGIFY_VERSION(MFTDECODER_MAJOR_VERSION,MFTDECODER_MINOR_VERSION,MFTDECODER_REVISION)
+
+/*======================= deconft utility ========================*/
+#define DECONFT_MAJOR_VERSION       BRCM_MAJOR_VERSION
+#define DECONFT_MINOR_VERSION       8
+#define DECONFT_REVISION            0
+
+#define DECONFT_RC_FILE_VERSION     STRINGIFY_VERSION(DECONFT_MAJOR_VERSION,DECONFT_MINOR_VERSION,DECONFT_REVISION)
+
+/*======================= Gensig utility ========================*/
+#define GENSIG_MAJOR_VERSION        BRCM_MAJOR_VERSION
+#define GENSIG_MINOR_VERSION        7
+#define GENSIG_REVISION             0
+
+#define GENSIG_RC_FILE_VERSION      STRINGIFY_VERSION(GENSIG_MAJOR_VERSION,GENSIG_MINOR_VERSION,GENSIG_REVISION)
+
+/*======================= FpgaProg utility ========================*/
+#define FPGAPROG_MAJOR_VERSION      BRCM_MAJOR_VERSION
+#define FPGAPROG_MINOR_VERSION      1
+#define FPGAPROG_REVISION           0
+
+#define FPGAPROG_RC_FILE_VERSION    STRINGIFY_VERSION(FPGAPROG_MAJOR_VERSION,FPGAPROG_MINOR_VERSION,FPGAPROG_REVISION)
+
+/*======================= CHDGensig DataBase Library ========================*/
+#define CHDGSDB_MAJOR_VERSION       BRCM_MAJOR_VERSION
+#define CHDGSDB_MINOR_VERSION       3
+#define CHDGSDB_REVISION            0
+
+#define CHDGSDB_RC_FILE_VERSION     STRINGIFY_VERSION(CHDGSDB_MAJOR_VERSION,CHDGSDB_MINOR_VERSION,CHDGSDB_REVISION)
+
+/*======================= CHDDosDiag utility ========================*/
+#define DOSDIAG_MAJOR_VERSION       BRCM_MAJOR_VERSION
+#define DOSDIAG_MINOR_VERSION       9
+#define DOSDIAG_REVISION            0
+
+#define DOSDIAG_RC_FILE_VERSION     STRINGIFY_VERSION(DOSDIAG_MAJOR_VERSION,DOSDIAG_MINOR_VERSION,DOSDIAG_REVISION)
+
+/*======================= CHDWinDiag utility ========================*/
+#define WINDIAG_MAJOR_VERSION       BRCM_MAJOR_VERSION
+#define WINDIAG_MINOR_VERSION       12
+#define WINDIAG_REVISION            0
+
+#define WINDIAG_RC_FILE_VERSION     STRINGIFY_VERSION(WINDIAG_MAJOR_VERSION,WINDIAG_MINOR_VERSION,WINDIAG_REVISION)
+
+/*======================= CHDWinInfo utility ========================*/
+#define WININFO_MAJOR_VERSION       BRCM_MAJOR_VERSION
+#define WININFO_MINOR_VERSION       1
+#define WININFO_REVISION            0
+
+#define WININFO_RC_FILE_VERSION     STRINGIFY_VERSION(WININFO_MAJOR_VERSION,WININFO_MINOR_VERSION,WININFO_REVISION)
+
+/*========================== WDM Encode Driver =================================*/
+#define	ENCODE_WDM_COMMENTS			"Broadcom Corp. BCM70013 Encoder\0"
+#define ENCODE_WDM_PRODUCT_NAME		"Broadcom Corp. MediaPC HD Video Encoder\0"
+#define ENCODE_WDM_PRIVATE_BUILD	"Broadcom Corp. Private\0"
+
+#define ENCODE_WDM_FILE_DESC		"Broadcom Corp BCM70013 WDM Driver\0"
+#define ENCODE_WDM_INTRL_NAME		"Link B0"
+#define ENCODE_WDM_ORIG_NAME		ENCODE_WDM_INTRL_NAME
+#define ENCODE_WDM_SPECIAL_BUILD	""
+
+#define ENCODE_WDM_MAJOR_VERSION	BRCM_MAJOR_VERSION
+#define ENCODE_WDM_MINOR_VERSION    0
+#define ENCODE_WDM_REVISION         1
+
+#define ENCODE_WDM_FILE_VERSION     STRINGIFY_VERSION(ENCODE_WDM_MAJOR_VERSION,ENCODE_WDM_MINOR_VERSION,ENCODE_WDM_REVISION) ".0"
+
+/*========================== CmdUtil Application ==============================*/
+#define CMDUTIL_MAJOR_VERSION        BRCM_MAJOR_VERSION
+#define CMDUTIL_MINOR_VERSION        0
+#define CMDUTIL_REVISION             0
+
+/*========================== CmdUtilt utility ==============================*/
+#define CMDUTILT_MAJOR_VERSION        BRCM_MAJOR_VERSION
+#define CMDUTILT_MINOR_VERSION        0
+#define CMDUTILT_REVISION
+
+#endif
diff --git a/ext/bcmdec/version_lnx.h b/ext/bcmdec/version_lnx.h
new file mode 100644
index 0000000..eb333f3
--- /dev/null
+++ b/ext/bcmdec/version_lnx.h
@@ -0,0 +1,111 @@
+/********************************************************************
+* Copyright(c) 2006 Broadcom Corporation.
+*
+*  Name: version_lnx.h
+*
+*  Description: Version numbering for the driver use.
+*
+*  AU
+*
+*  HISTORY:
+*
+*******************************************************************
+*
+* 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.
+*
+* 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, see <http://www.gnu.org/licenses/>.
+*
+*******************************************************************/
+
+#ifndef _BC_DTS_VERSION_LNX_
+#define _BC_DTS_VERSION_LNX_
+//
+// The version format that we are adopting is
+// MajorVersion.MinorVersion.Revision
+// This will be the same for all the components.
+//
+//
+#define STRINGIFY_VERSION(MAJ,MIN,REV) STRINGIFIED_VERSION(MAJ,MIN,REV)
+#define STRINGIFIED_VERSION(MAJ,MIN,REV) #MAJ "." #MIN "." #REV
+
+#define STRINGIFY_VERSION_W(MAJ,MIN,REV) STRINGIFIED_VERSION_W(MAJ,MIN,REV)
+#define STRINGIFIED_VERSION_W(MAJ,MIN,REV) #MAJ "." #MIN "." #REV
+
+//
+//  Product Version number is:
+//  x.y.z.a
+//
+//  x = Major release.      1 = Dozer, 2 = Dozer + Link
+//  y = Minor release.      Should increase +1 per "real" release.
+//  z = Branch release.     0 for main branch.  This is +1 per branch release.
+//  a = Build number        +1 per candidate release.  Reset to 0 every "real" release.
+//
+//
+// Enabling Check-In rules enforcement 08092007
+//
+#define INVALID_VERSION             0xFFFF
+
+/*========================== Common For All Components =================================*/
+#define RC_COMPANY_NAME             "Broadcom Corporation\0"
+#define RC_PRODUCT_VERSION          "2.7.0.23"
+#define RC_W_PRODUCT_VERSION        L"2.7.0.23"
+#define RC_PRODUCT_NAME             "Broadcom Video Decoder\0"
+#define RC_COMMENTS                 "Broadcom BCM70010/BCM70012 Controller\0"
+#define RC_COPYRIGHT                "Copyright(c) 2007 Broadcom Corporation"
+#define RC_PRIVATE_BUILD            "Broadcom Corp. Private\0"
+#define RC_LEGAL_TRADEMARKS         " \0"
+#define BRCM_MAJOR_VERSION          0
+
+
+/*========================== WDM Driver =================================*/
+
+/*
+ * Version number scheme for driver DVMJVer.DVMNVer.DVRev.UNMODIFIED
+ * Where DVMJVer = DRIVER_MAJOR_VERSION
+ * DVMNVer = DRIVER_MINOR_VERSION
+ * DVRev = DRIVER_REVISION
+ * UNMODIFIED = This is for Compatibility with windows INF file version scheme.
+ */
+
+#define RC_FILE_DESCRIPTION         "Broadcom BCM70010/BCM70012 Driver\0"
+#define RC_INTERNAL_NAME            ""
+#define RC_ORIGINAL_NAME            RC_INTERNAL_NAME
+#define RC_SPECIAL_BUILD            ""
+
+#define DRIVER_MAJOR_VERSION        BRCM_MAJOR_VERSION
+#define DRIVER_MINOR_VERSION        1
+#define DRIVER_REVISION             0
+
+#define RC_FILE_VERSION             STRINGIFY_VERSION(DRIVER_MAJOR_VERSION,DRIVER_MINOR_VERSION,DRIVER_REVISION) ".0"
+
+/*======================= Device Interface Library ========================*/
+#define DIL_MAJOR_VERSION           BRCM_MAJOR_VERSION
+#define DIL_MINOR_VERSION           1
+#define DIL_REVISION                0
+
+#define DIL_RC_FILE_VERSION         STRINGIFY_VERSION(DIL_MAJOR_VERSION,DIL_MINOR_VERSION,DIL_REVISION)
+
+/*========================== deconf utility ==============================*/
+#define DECONF_MAJOR_VERSION        BRCM_MAJOR_VERSION
+#define DECONF_MINOR_VERSION        1
+#define DECONF_REVISION             0
+#define DECONF_RC_FILE_VERSION      STRINGIFY_VERSION(DIL_MAJOR_VERSION,DIL_MINOR_VERSION,DIL_REVISION)
+
+#ifndef _PB_FIX_ME_
+/*======================= deconft utility ========================*/
+#define DECONFT_MAJOR_VERSION       BRCM_MAJOR_VERSION
+#define DECONFT_MINOR_VERSION       1
+#define DECONFT_REVISION            0
+
+#define DECONFT_RC_FILE_VERSION     STRINGIFY_VERSION(DECONFT_MAJOR_VERSION,DECONFT_MINOR_VERSION,DECONFT_REVISION)
+#endif
+
+
+#endif
