]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugin-ducati.git/blobdiff - src/gstducatividdec.c
mpeg2dec: Fix negotiation issue with playbin
[glsdk/gst-plugin-ducati.git] / src / gstducatividdec.c
index 5cd95b438a7d718792704ba0c17217c81af90554..e94ddc55f8f61da4b1d08f3839633868d3f5efb2 100644 (file)
  */
 
 #ifdef HAVE_CONFIG_H
-#  include <config.h>
+#include <config.h>
 #endif
 
 #include "gstducatividdec.h"
 #include "gstducatibufferpriv.h"
+#include <stdlib.h>
 
 #define VERSION_LENGTH 256
-GST_BOILERPLATE (GstDucatiVidDec, gst_ducati_viddec, GstElement,
-    GST_TYPE_ELEMENT);
+
+static void gst_ducati_viddec_class_init (GstDucatiVidDecClass * klass);
+static void gst_ducati_viddec_init (GstDucatiVidDec * self, gpointer klass);
+static void gst_ducati_viddec_base_init (gpointer gclass);
+static GstElementClass *parent_class = NULL;
+
+GType
+gst_ducati_viddec_get_type (void)
+{
+  static GType ducati_viddec_type = 0;
+
+  if (!ducati_viddec_type) {
+    static const GTypeInfo ducati_viddec_info = {
+      sizeof (GstDucatiVidDecClass),
+      (GBaseInitFunc) gst_ducati_viddec_base_init,
+      NULL,
+      (GClassInitFunc) gst_ducati_viddec_class_init,
+      NULL,
+      NULL,
+      sizeof (GstDucatiVidDec),
+      0,
+      (GInstanceInitFunc) gst_ducati_viddec_init,
+    };
+
+    ducati_viddec_type = g_type_register_static (GST_TYPE_ELEMENT,
+        "GstDucatiVidDec", &ducati_viddec_info, 0);
+  }
+  return ducati_viddec_type;
+}
 
 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("NV12"))
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("NV12"))
     );
 
 enum
@@ -131,11 +159,6 @@ engine_open (GstDucatiVidDec * self)
 static void
 codec_delete (GstDucatiVidDec * self)
 {
-  if (self->pool) {
-    gst_drm_buffer_pool_destroy (self->pool);
-    self->pool = NULL;
-  }
-
   if (self->codec) {
     GST_DEBUG ("Calling VIDDEC3_delete");
     VIDDEC3_delete (self->codec);
@@ -144,7 +167,9 @@ codec_delete (GstDucatiVidDec * self)
 
   if (self->input_bo) {
     omap_bo_del (self->input_bo);
+    close ((int) self->inBufs->descs[0].buf);
     self->input_bo = NULL;
+    self->input = NULL;
   }
 }
 
@@ -187,7 +212,7 @@ codec_create (GstDucatiVidDec * self)
   }
 
   self->first_in_buffer = TRUE;
-  self->first_out_buffer = TRUE;
+  self->first_out_buffer = FALSE;
 
   version = dce_alloc (VERSION_LENGTH);
   if (version) {
@@ -235,44 +260,74 @@ codec_create (GstDucatiVidDec * self)
 static inline GstBuffer *
 codec_buffer_pool_get (GstDucatiVidDec * self, GstBuffer * buf)
 {
+  GstBuffer *ret_buf;
+  GstCaps *caps = gst_pad_get_current_caps (self->srcpad);
+  GstStructure *conf;
+  GstVideoInfo info;
+  if (!gst_video_info_from_caps (&info, caps)) {
+    GST_WARNING_OBJECT (self, "No valid pad caps");
+  }
   if (G_UNLIKELY (!self->pool)) {
-    guint size = gst_video_format_get_size (GST_VIDEO_FORMAT_NV12,
-        self->padded_width, self->padded_height);
+    GstAllocator *allocator;
+    int num_buffers = 0;
+    guint size =
+        GST_ROUND_UP_4 (self->padded_width) *
+        GST_ROUND_UP_2 (self->padded_height) * 3 / 2;
+
+    if (self->status->maxNumDisplayBufs)
+      num_buffers = MAX (4, self->status->maxNumDisplayBufs);
 
     GST_DEBUG_OBJECT (self, "creating bufferpool");
-    self->pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
-        dce_get_fd (), GST_PAD_CAPS (self->srcpad), size);
-  }
-  return GST_BUFFER (gst_drm_buffer_pool_get (self->pool, FALSE));
+    GST_DEBUG_OBJECT (self, "%s\n",
+        gst_caps_to_string (gst_pad_get_current_caps (self->srcpad)));
+
+    allocator = gst_drm_allocator_get ();
+
+    if (!allocator) {
+      GST_DEBUG_OBJECT (self,
+          "Did not get a DRM allocator. Proceeding with default allocator");
+    }
+    self->pool = gst_buffer_pool_new ();
+    conf = gst_buffer_pool_get_config (GST_BUFFER_POOL (self->pool));
+    gst_buffer_pool_config_set_params (conf, caps, size, num_buffers,
+        num_buffers);
+    gst_buffer_pool_config_set_allocator (conf, allocator, NULL);
+    gst_buffer_pool_set_config (GST_BUFFER_POOL (self->pool), conf);
+    gst_buffer_pool_set_active (GST_BUFFER_POOL (self->pool), TRUE);
+  }
+  gst_buffer_pool_acquire_buffer (self->pool, &ret_buf, NULL);
+  gst_buffer_add_video_crop_meta (ret_buf);
+  /* Crop meta will be checked and consumed by codec_process */
+
+  return ret_buf;
 }
 
-static GstDucatiBufferPriv *
+static GstMetaDucatiBufferPriv *
 get_buffer_priv (GstDucatiVidDec * self, GstBuffer * buf)
 {
-  GstDucatiBufferPriv *priv = gst_ducati_buffer_priv_get (buf);
+  GstMetaDucatiBufferPriv *priv = gst_ducati_buffer_priv_get (buf);
   if (!priv) {
     GstVideoFormat format = GST_VIDEO_FORMAT_NV12;
-    GstDmaBuf *dmabuf = gst_buffer_get_dma_buf (buf);
+    struct omap_bo *bo;
+    gint uv_offset, size;
+    GstMemory *mem = gst_buffer_peek_memory (buf, 0);
+    int fd = gst_fd_memory_get_fd (mem);
 
     /* if it isn't a dmabuf buffer that we can import, then there
      * is nothing we can do with it:
      */
-    if (!dmabuf) {
+    if (fd < 0) {
       GST_DEBUG_OBJECT (self, "not importing non dmabuf buffer");
       return NULL;
     }
 
-    priv = gst_ducati_buffer_priv_new ();
-
-    priv->bo = omap_bo_from_dmabuf (self->device, gst_dma_buf_get_fd (dmabuf));
-
-    priv->uv_offset = gst_video_format_get_component_offset (format,
-        1, self->stride, self->padded_height);
-    priv->size = gst_video_format_get_size (format,
-        self->stride, self->padded_height);
-
-    gst_ducati_buffer_priv_set (buf, priv);
-    gst_mini_object_unref (GST_MINI_OBJECT (priv));
+    bo = omap_bo_from_dmabuf (self->device, fd);
+    uv_offset =
+        GST_ROUND_UP_4 (self->stride) * GST_ROUND_UP_2 (self->padded_height);
+    size =
+        GST_ROUND_UP_4 (self->stride) * GST_ROUND_UP_2 (self->padded_height) *
+        3 / 2;
+    priv = gst_ducati_buffer_priv_set (buf, bo, uv_offset, size);
   }
   return priv;
 }
@@ -281,8 +336,8 @@ static XDAS_Int32
 codec_prepare_outbuf (GstDucatiVidDec * self, GstBuffer ** buf,
     gboolean force_internal)
 {
-  GstDucatiBufferPriv *priv = NULL;
-  GstDmaBuf *dmabuf = NULL;
+  GstMetaDucatiBufferPriv *priv = NULL;
+  int fd = -1;
 
   if (!force_internal)
     priv = get_buffer_priv (self, *buf);
@@ -292,7 +347,7 @@ codec_prepare_outbuf (GstDucatiVidDec * self, GstBuffer ** buf,
 
     GST_DEBUG_OBJECT (self, "internal bufferpool forced");
     *buf = codec_buffer_pool_get (self, NULL);
-    GST_BUFFER_TIMESTAMP (*buf) = GST_BUFFER_TIMESTAMP (orig);
+    GST_BUFFER_PTS (*buf) = GST_BUFFER_PTS (orig);
     GST_BUFFER_DURATION (*buf) = GST_BUFFER_DURATION (orig);
     gst_buffer_unref (orig);
     return codec_prepare_outbuf (self, buf, FALSE);
@@ -300,11 +355,18 @@ codec_prepare_outbuf (GstDucatiVidDec * self, GstBuffer ** buf,
 
   /* There are at least two buffers. Derived classes may add codec specific
      buffers (eg, debug info) after these two if they want to. */
-  dmabuf = gst_buffer_get_dma_buf (*buf);
+  GstMemory *mem = gst_buffer_peek_memory (*buf, 0);
+  fd = gst_fd_memory_get_fd (mem);
+
+  if (fd < 0) {
+    GST_DEBUG_OBJECT (self, "Invalid fd");
+    return 0;
+  }
+
   /* XDM_MemoryType required by drm to allcoate buffer */
   self->outBufs->descs[0].memType = XDM_MEMTYPE_RAW;
   /* IPC requires dmabuf fd in place of bo handle */
-  self->outBufs->descs[0].buf = (XDAS_Int8 *) gst_dma_buf_get_fd (dmabuf);
+  self->outBufs->descs[0].buf = (XDAS_Int8 *) fd;
   self->outBufs->descs[0].bufSize.bytes = priv->uv_offset;
   self->outBufs->descs[1].memType = XDM_MEMTYPE_RAW;
   /* For singleplaner buffer pass a single dmabuf fd for both the outBufs
@@ -331,22 +393,62 @@ codec_get_outbuf (GstDucatiVidDec * self, XDAS_Int32 id)
   return buf;
 }
 
+static void
+do_dce_buf_unlock (GstBuffer * buf)
+{
+  SizeT fd;
+  /* Get dmabuf fd of the buffer to unlock */
+  GstMemory *mem = gst_buffer_peek_memory (buf, 0);
+  fd = gst_fd_memory_get_fd (mem);
+
+  if (fd < 0) {
+    GST_DEBUG ("Invalid Fd to unlock");
+    return;
+  }
+  dce_buf_unlock (1, &fd);
+}
+
+static void
+dce_buf_free_all (GstBuffer * buf, gpointer key, GstDucatiVidDec * self)
+{
+  if (FALSE == g_hash_table_remove (self->passed_in_bufs, buf)) {
+    /* Buffer was not found in the hash table, remove it anyway */
+    gst_buffer_unref (buf);
+  }
+}
+
 static void
 codec_unlock_outbuf (GstDucatiVidDec * self, XDAS_Int32 id)
 {
   GstBuffer *buf = (GstBuffer *) id;
-  SizeT fd;
 
   if (buf) {
     GST_DEBUG_OBJECT (self, "free buffer: %d %p", id, buf);
-    /* Get dmabuf fd of the buffer to unlock */
-    fd = gst_dma_buf_get_fd(gst_buffer_get_dma_buf(buf));
     /* Must unlock the buffer before free */
-    dce_buf_unlock(1,&fd);
-    g_hash_table_remove (self->passed_in_bufs, buf);
+    g_hash_table_remove (self->dce_locked_bufs, buf);
+    if (FALSE == g_hash_table_remove (self->passed_in_bufs, buf)) {
+      /* Buffer was not found in the hash table, remove it anyway */
+      gst_buffer_unref (buf);
+    }
   }
 }
 
+/* Called when playing in reverse */
+static GstFlowReturn
+gst_ducati_viddec_push_latest (GstDucatiVidDec * self)
+{
+  GstBuffer *buf;
+
+  if (self->backlog_nframes == 0)
+    return GST_FLOW_OK;
+
+  /* send it, giving away the ref */
+  buf = self->backlog_frames[--self->backlog_nframes];
+  GST_DEBUG_OBJECT (self, "Actually pushing backlog buffer %" GST_PTR_FORMAT,
+      buf);
+  return gst_pad_push (self->srcpad, buf);
+}
+
 static GstFlowReturn
 gst_ducati_viddec_push_earliest (GstDucatiVidDec * self)
 {
@@ -378,9 +480,18 @@ gst_ducati_viddec_push_earliest (GstDucatiVidDec * self)
 static void
 gst_ducati_viddec_on_flush (GstDucatiVidDec * self, gboolean eos)
 {
-  /* push everything on the backlog, ignoring errors */
-  while (self->backlog_nframes > 0) {
-    gst_ducati_viddec_push_earliest (self);
+  if (self->segment.format == GST_FORMAT_TIME &&
+      self->segment.rate < (gdouble) 0.0) {
+    /* negative rate */
+    /* push everything on the backlog, ignoring errors */
+    while (self->backlog_nframes > 0) {
+      gst_ducati_viddec_push_latest (self);
+    }
+  } else {
+    /* push everything on the backlog, ignoring errors */
+    while (self->backlog_nframes > 0) {
+      gst_ducati_viddec_push_earliest (self);
+    }
   }
 }
 
@@ -388,7 +499,7 @@ static gint
 codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush,
     GstFlowReturn * flow_ret)
 {
-  gint err;
+  gint err, getstatus_err;
   GstClockTime t;
   GstBuffer *outbuf = NULL;
   gint i;
@@ -403,13 +514,50 @@ codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush,
   memset (&self->outArgs->freeBufID, 0, sizeof (self->outArgs->freeBufID));
 
   if (self->inArgs->inputID != 0) {
-         /* Get dmabuf fd of the buffer to lock it*/
-         fd = gst_dma_buf_get_fd(gst_buffer_get_dma_buf((GstBuffer *) self->inArgs->inputID));
-         /* Must lock all the buffer passed to ducati */
-         dce_buf_lock(1,&fd);
+    /* Check if this inputID was already sent to the codec */
+    if (g_hash_table_contains (self->dce_locked_bufs,
+            (gpointer) self->inArgs->inputID)) {
+      int out_fd = -1;
+      GstMetaDucatiBufferPriv *priv =
+          gst_ducati_buffer_priv_get ((GstBuffer *) self->inArgs->inputID);
+
+      GST_DEBUG_OBJECT (self, "Resending (inputID: %08x)",
+          self->inArgs->inputID);
+      /* Input ID needs to be resent to the codec for cases like H.264 field coded pictures.
+         The decoder indicates this by setting outArgs->outBufsInUseFlag */
+      self->outBufs->descs[0].memType = XDM_MEMTYPE_RAW;
+
+      GstMemory *mem =
+          gst_buffer_peek_memory ((GstBuffer *) self->inArgs->inputID, 0);
+      out_fd = gst_fd_memory_get_fd (mem);
+      if (out_fd < 0) {
+        GST_DEBUG_OBJECT (self, "Invalid fd %d", out_fd);
+        gst_buffer_unref (((GstBuffer *) self->inArgs->inputID));
+        return GST_FLOW_ERROR;
+      }
+      self->outBufs->descs[0].buf = (XDAS_Int8 *) out_fd;
+      self->outBufs->descs[0].bufSize.bytes = priv->uv_offset;
+      self->outBufs->descs[1].memType = XDM_MEMTYPE_RAW;
+      self->outBufs->descs[1].buf = (XDAS_Int8 *) self->outBufs->descs[0].buf;
+      self->outBufs->descs[1].bufSize.bytes = priv->size - priv->uv_offset;
+    } else {
+      /* Get dmabuf fd of the buffer to lock it */
+      GstMemory *mem =
+          gst_buffer_peek_memory ((GstBuffer *) self->inArgs->inputID, 0);
+      fd = gst_fd_memory_get_fd (mem);
+      if (fd < 0) {
+        GST_DEBUG_OBJECT (self, "Invalid fd %d", fd);
+        gst_buffer_unref (((GstBuffer *) self->inArgs->inputID));
+        return GST_FLOW_ERROR;
+      }
+      /* Must lock all the buffer passed to ducati */
+      GST_DEBUG_OBJECT (self, "dce_buf_lock(inputID: %08x, fd: %d)",
+          self->inArgs->inputID, fd);
+      dce_buf_lock (1, &fd);
+      g_hash_table_insert (self->dce_locked_bufs,
+          (gpointer) self->inArgs->inputID, (gpointer) self->inArgs->inputID);
+    }
   }
-
-  GST_DEBUG ("Calling VIDDEC3_process");
   t = gst_util_get_timestamp ();
   err = VIDDEC3_process (self->codec,
       self->inBufs, self->outBufs, self->inArgs, self->outArgs);
@@ -422,17 +570,44 @@ codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush,
         err, self->outArgs->extendedError);
     gst_ducati_log_extended_error_info (self->outArgs->extendedError,
         self->error_strings);
+  }
 
+  if (err || self->first_in_buffer) {
     GST_DEBUG ("Calling VIDDEC3_control XDM_GETSTATUS");
-    err = VIDDEC3_control (self->codec, XDM_GETSTATUS,
+    getstatus_err = VIDDEC3_control (self->codec, XDM_GETSTATUS,
         self->dynParams, self->status);
-    if (err) {
+    if (getstatus_err) {
       GST_WARNING_OBJECT (self, "XDM_GETSTATUS: err=%d, extendedError=%08x",
-          err, self->status->extendedError);
+          getstatus_err, self->status->extendedError);
       gst_ducati_log_extended_error_info (self->status->extendedError,
           self->error_strings);
     }
 
+    if (!getstatus_err && self->first_in_buffer) {
+      if (send && self->status->maxNumDisplayBufs != 0) {
+        GstCaps *caps;
+        GST_WARNING_OBJECT (self, "changing max-ref-frames in caps to %d",
+            self->status->maxNumDisplayBufs);
+
+        caps = gst_caps_make_writable (gst_pad_get_current_caps (self->srcpad));
+
+        gst_caps_set_simple (caps, "max-ref-frames", G_TYPE_INT,
+            self->status->maxNumDisplayBufs, NULL);
+        if (!gst_pad_set_caps (self->srcpad, caps)) {
+          GST_ERROR_OBJECT (self, "downstream didn't accept new caps");
+          err = XDM_EFAIL;
+        }
+
+        if (self->pool) {
+          gst_object_unref (self->pool);
+          self->pool = NULL;
+        }
+        gst_caps_unref (caps);
+      }
+    }
+  }
+
+  if (err) {
     if (flush)
       err = XDM_EFAIL;
     else
@@ -449,12 +624,29 @@ codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush,
   for (i = 0; i < IVIDEO2_MAX_IO_BUFFERS && self->outArgs->outputID[i]; i++) {
     gboolean interlaced;
 
-    /* Getting an extra reference for the decoder */
-    outbuf = codec_get_outbuf (self, self->outArgs->outputID[i]);
+    GST_DEBUG_OBJECT (self, "VIDDEC3_process outputID[%d]: %08x",
+        i, self->outArgs->outputID[i]);
     interlaced =
-        self->outArgs->decodedBufs.contentType ==
+        self->outArgs->displayBufs.bufDesc[0].contentType ==
         IVIDEO_PROGRESSIVE ? FALSE : TRUE;
 
+    if (interlaced) {
+      GstBuffer *buf = GST_BUFFER (self->outArgs->outputID[i]);
+      if (!buf || !gst_buffer_is_writable (buf)) {
+        GST_ERROR_OBJECT (self, "Cannot change buffer flags!!");
+      } else {
+        GST_BUFFER_FLAG_UNSET (buf, GST_VIDEO_BUFFER_FLAG_TFF);
+        GST_BUFFER_FLAG_UNSET (buf, GST_VIDEO_BUFFER_FLAG_RFF);
+        if (self->outArgs->displayBufs.bufDesc[0].topFieldFirstFlag)
+          GST_BUFFER_FLAG_SET (buf, GST_VIDEO_BUFFER_FLAG_TFF);
+        if (self->outArgs->displayBufs.bufDesc[0].repeatFirstFieldFlag)
+          GST_BUFFER_FLAG_SET (buf, GST_VIDEO_BUFFER_FLAG_RFF);
+      }
+    }
+
+    /* Getting an extra reference for the decoder */
+    outbuf = codec_get_outbuf (self, self->outArgs->outputID[i]);
+
     /* if send is FALSE, don't try to renegotiate as we could be flushing during
      * a PAUSED->READY state change
      */
@@ -467,70 +659,66 @@ codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush,
 
       self->interlaced = interlaced;
 
-      caps =
-          gst_caps_make_writable (gst_pad_get_negotiated_caps (self->srcpad));
+      caps = gst_caps_make_writable (gst_pad_get_current_caps (self->srcpad));
       GST_INFO_OBJECT (self, "changing interlace field in caps");
       gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, interlaced,
           NULL);
-      gst_drm_buffer_pool_set_caps (self->pool, caps);
       if (!gst_pad_set_caps (self->srcpad, caps)) {
         GST_ERROR_OBJECT (self,
             "downstream didn't want to change interlace mode");
         err = XDM_EFAIL;
       }
       gst_caps_unref (caps);
-
-      /* this buffer still has the old caps so we skip it */
-      send = FALSE;
     }
 
-    if (G_UNLIKELY (self->send_crop_event) && send) {
-      gint crop_width, crop_height;
-
-      /* send region of interest to sink on first buffer: */
-      XDM_Rect *r = &(self->outArgs->displayBufs.bufDesc[0].activeFrameRegion);
-
-      crop_width = r->bottomRight.x - r->topLeft.x;
-      crop_height = r->bottomRight.y - r->topLeft.y;
-
-      if (crop_width > self->input_width)
-        crop_width = self->input_width;
-      if (crop_height > self->input_height)
-        crop_height = self->input_height;
-
-      GST_INFO_OBJECT (self, "active frame region %d, %d, %d, %d, crop %dx%d",
-          r->topLeft.x, r->topLeft.y, r->bottomRight.x, r->bottomRight.y,
-          crop_width, crop_height);
-
-      gst_pad_push_event (self->srcpad,
-          gst_event_new_crop (r->topLeft.y, r->topLeft.x,
-              crop_width, crop_height));
-
-      if (self->crop)
-        gst_video_crop_unref (self->crop);
-
-      self->crop = gst_video_crop_new (r->topLeft.y, r->topLeft.x,
-          crop_width, crop_height);
-
-      self->send_crop_event = FALSE;
+    if (send) {
+      GstVideoCropMeta *crop = gst_buffer_get_video_crop_meta (outbuf);
+      if (crop) {
+        gint crop_width, crop_height;
+        /* send region of interest to sink on first buffer: */
+        XDM_Rect *r =
+            &(self->outArgs->displayBufs.bufDesc[0].activeFrameRegion);
+
+        crop_width = r->bottomRight.x - r->topLeft.x;
+        crop_height = r->bottomRight.y - r->topLeft.y;
+
+        if (crop_width > self->input_width)
+          crop_width = self->input_width;
+        if (crop_height > self->input_height)
+          crop_height = self->input_height;
+
+        GST_INFO_OBJECT (self, "active frame region %d, %d, %d, %d, crop %dx%d",
+            r->topLeft.x, r->topLeft.y, r->bottomRight.x, r->bottomRight.y,
+            crop_width, crop_height);
+
+        crop->x = r->topLeft.x;
+        crop->y = r->topLeft.y;
+        crop->width = crop_width;
+        crop->height = crop_height;
+      } else {
+        GST_INFO_OBJECT (self, "Crop metadata not present in buffer");
+      }
     }
 
     if (G_UNLIKELY (self->first_out_buffer) && send) {
-      GstDRMBufferPool *pool;
+
       self->first_out_buffer = FALSE;
 
       /* Destroy the pool so the buffers we used so far are eventually released.
        * The pool will be recreated if needed.
        */
-      pool = self->pool;
-      self->pool = NULL;
-      gst_drm_buffer_pool_destroy (pool);
+
+      if (self->pool) {
+        gst_object_unref (self->pool);
+        self->pool = NULL;
+      }
+
     }
 
     if (send) {
       GstClockTime ts;
 
-      ts = GST_BUFFER_TIMESTAMP (outbuf);
+      ts = GST_BUFFER_PTS (outbuf);
 
       GST_DEBUG_OBJECT (self, "got buffer: %d %p (%" GST_TIME_FORMAT ")",
           i, outbuf, GST_TIME_ARGS (ts));
@@ -553,26 +741,11 @@ codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush,
 
       if (self->ts_is_pts) {
         /* if we have a queued DTS from demuxer, use that instead: */
-        GST_BUFFER_TIMESTAMP (outbuf) = ts;
+        GST_BUFFER_PTS (outbuf) = ts;
         GST_DEBUG_OBJECT (self, "fixed ts: %d %p (%" GST_TIME_FORMAT ")",
             i, outbuf, GST_TIME_ARGS (ts));
       }
 
-      if (GST_BUFFER_CAPS (outbuf) &&
-          !gst_caps_is_equal (GST_BUFFER_CAPS (outbuf),
-              GST_PAD_CAPS (self->srcpad))) {
-        /* this looks a bit scary but it's really just to change the interlace=
-         * field in caps when we start as !interlaced and the codec detects
-         * otherwise */
-        GST_WARNING_OBJECT (self, "overriding buffer caps to fix "
-            "interlace mismatch");
-        outbuf = gst_buffer_make_metadata_writable (outbuf);
-        gst_buffer_set_caps (outbuf, GST_PAD_CAPS (self->srcpad));
-      }
-
-      if (self->crop)
-        gst_buffer_set_video_crop (outbuf, self->crop);
-
       ret = klass->push_output (self, outbuf);
       if (flow_ret)
         *flow_ret = ret;
@@ -591,9 +764,20 @@ codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush,
 
 skip_outbuf_processing:
   for (i = 0; i < IVIDEO2_MAX_IO_BUFFERS && self->outArgs->freeBufID[i]; i++) {
+    GST_DEBUG_OBJECT (self, "VIDDEC3_process freeBufID[%d]: %08x",
+        i, self->outArgs->freeBufID[i]);
     codec_unlock_outbuf (self, self->outArgs->freeBufID[i]);
   }
 
+  /* The following condition will occur when it is 
+   * not a normal flush and remote proc has crashed */
+  if (!flush && err == XDM_EFAIL) {
+    codec_delete (self);
+    self->codec = NULL;
+    engine_close (self);
+    exit (-1);
+  }
+
   return err;
 }
 
@@ -656,6 +840,8 @@ gst_ducati_viddec_codec_flush (GstDucatiVidDec * self, gboolean eos)
 
   /* We flushed the decoder, we can now remove the buffer that have never been
    * unrefed in it */
+  g_hash_table_foreach (self->dce_locked_bufs, (GHFunc) dce_buf_free_all, self);
+  g_hash_table_remove_all (self->dce_locked_bufs);
   g_hash_table_remove_all (self->passed_in_bufs);
 
   /* reset outArgs in case we're flushing in codec_process trying to do error
@@ -695,30 +881,58 @@ gst_ducati_viddec_parse_caps (GstDucatiVidDec * self, GstStructure * s)
     h = ALIGN2 (self->input_height, 4); /* round up to MB */
     w = ALIGN2 (self->input_width, 4);  /* round up to MB */
 
+
+  } else {
+
+    h = ALIGN2 (1080, 4); /* round up to MB */
+    w = ALIGN2 (1920, 4);  /* round up to MB */
+  }
+
     /* if we've already created codec, but the resolution has changed, we
      * need to re-create the codec:
      */
-    if (G_UNLIKELY (self->codec)) {
-      if ((h != self->height) || (w != self->width)) {
-        codec_delete (self);
-      }
+    if (G_UNLIKELY ((self->codec) && ((h != self->height) || (w != self->width)
+                || self->codec_create_params_changed))) {
+      GST_DEBUG_OBJECT (self, "%dx%d => %dx%d, %d", self->width,
+          self->height, w, h, self->codec_create_params_changed);
+      codec_delete (self);
     }
 
+    self->codec_create_params_changed = FALSE;
     self->width = w;
     self->height = h;
 
     codec_data = gst_structure_get_value (s, "codec_data");
 
     if (codec_data) {
+      int i;
+      GstMapInfo info;
+      gboolean mapped;
       GstBuffer *buffer = gst_value_get_buffer (codec_data);
+
       GST_DEBUG_OBJECT (self, "codec_data: %" GST_PTR_FORMAT, buffer);
-      self->codec_data = gst_buffer_ref (buffer);
-    }
 
-    return TRUE;
-  }
+      mapped = gst_buffer_map (buffer, &info, GST_MAP_READ);
+      GST_DEBUG_OBJECT (self, "codec_data dump, size = %d ", info.size);
+      for (i = 0; i < info.size; i++) {
+        GST_DEBUG_OBJECT (self, "%02x ", info.data[i]);
+      }
+      if (info.size) {
+        self->codecdata = g_slice_alloc (info.size);
+        if (self->codecdata) {
+          memcpy (self->codecdata, info.data, info.size);
+        } else {
+          GST_DEBUG_OBJECT (self, "g_slice_alloc failed");
+        }
+        self->codecdatasize = info.size;
+      }
+      if (mapped) {
+        gst_buffer_unmap (buffer, &info);
+      }
 
-  return FALSE;
+    }
+
+  return TRUE;
 }
 
 static gboolean
@@ -791,13 +1005,18 @@ gst_ducati_viddec_allocate_params (GstDucatiVidDec * self, gint params_sz,
 static GstBuffer *
 gst_ducati_viddec_push_input (GstDucatiVidDec * self, GstBuffer * buf)
 {
-  if (G_UNLIKELY (self->first_in_buffer) && self->codec_data) {
-    push_input (self, GST_BUFFER_DATA (self->codec_data),
-        GST_BUFFER_SIZE (self->codec_data));
+  GstMapInfo info;
+  gboolean mapped;
+  if (G_UNLIKELY (self->first_in_buffer) && self->codecdata) {
+    push_input (self, self->codecdata, self->codecdatasize);
   }
-
   /* just copy entire buffer */
-  push_input (self, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+
+  mapped = gst_buffer_map (buf, &info, GST_MAP_READ);
+  if (mapped) {
+    push_input (self, info.data, info.size);
+    gst_buffer_unmap (buf, &info);
+  }
   gst_buffer_unref (buf);
 
   return NULL;
@@ -808,23 +1027,50 @@ gst_ducati_viddec_push_output (GstDucatiVidDec * self, GstBuffer * buf)
 {
   GstFlowReturn ret = GST_FLOW_OK;
 
-  /* if no reordering info was set, just send the buffer */
-  if (GST_BUFFER_OFFSET_END (buf) == GST_BUFFER_OFFSET_NONE) {
-    GST_DEBUG_OBJECT (self, "No reordering info on that buffer, sending now");
-    return gst_pad_push (self->srcpad, buf);
-  }
+  if (self->segment.format == GST_FORMAT_TIME &&
+      self->segment.rate < (gdouble) 0.0) {
+    /* negative rate: reverse playback */
+
+    if (self->backlog_nframes > 0 &&
+        (GST_BUFFER_PTS (self->backlog_frames[0]) > GST_BUFFER_PTS (buf))) {
+      /* push out all backlog frames, since we have a buffer that is
+         earlier than any other in the list */
+      while (self->backlog_nframes > 0) {
+        ret = gst_ducati_viddec_push_latest (self);
+        if (ret != GST_FLOW_OK)
+          break;
+      }
+    }
+    /* add the frame to the list, the array will own the ref */
+    GST_DEBUG_OBJECT (self, "Adding buffer %" GST_PTR_FORMAT " to backlog",
+        buf);
+    if (self->backlog_nframes < MAX_BACKLOG_ARRAY_SIZE) {
+      self->backlog_frames[self->backlog_nframes++] = buf;
+    } else {
+      /* No space in the re-order buffer, drop the frame */
+      GST_WARNING_OBJECT (self, "Dropping buffer %" GST_PTR_FORMAT, buf);
+      gst_buffer_unref (buf);
+    }
 
-  /* add the frame to the list, the array will own the ref */
-  GST_DEBUG_OBJECT (self, "Adding buffer %" GST_PTR_FORMAT " to backlog", buf);
-  self->backlog_frames[self->backlog_nframes++] = buf;
+  } else {
+    /* if no reordering info was set, just send the buffer */
+    if (GST_BUFFER_OFFSET_END (buf) == GST_BUFFER_OFFSET_NONE) {
+      GST_DEBUG_OBJECT (self, "No reordering info on that buffer, sending now");
+      return gst_pad_push (self->srcpad, buf);
+    }
 
-  /* push till we have no more than the max needed, or error */
-  while (self->backlog_nframes > self->backlog_maxframes) {
-    ret = gst_ducati_viddec_push_earliest (self);
-    if (ret != GST_FLOW_OK)
-      break;
-  }
+    /* add the frame to the list, the array will own the ref */
+    GST_DEBUG_OBJECT (self, "Adding buffer %" GST_PTR_FORMAT " to backlog",
+        buf);
+    self->backlog_frames[self->backlog_nframes++] = buf;
 
+    /* push till we have no more than the max needed, or error */
+    while (self->backlog_nframes > self->backlog_maxframes) {
+      ret = gst_ducati_viddec_push_earliest (self);
+      if (ret != GST_FLOW_OK)
+        break;
+    }
+  }
   return ret;
 }
 
@@ -832,7 +1078,8 @@ static gint
 gst_ducati_viddec_handle_error (GstDucatiVidDec * self, gint ret,
     gint extended_error, gint status_extended_error)
 {
-  if (XDM_ISFATALERROR (extended_error))
+  if (XDM_ISFATALERROR (extended_error) || (ret == DCE_EXDM_UNSUPPORTED)
+      || (ret == DCE_EIPC_CALL_FAIL) || (ret == DCE_EINVALID_INPUT))
     ret = XDM_EFAIL;
   else
     ret = XDM_EOK;
@@ -853,6 +1100,8 @@ gst_ducati_viddec_set_sink_caps (GstDucatiVidDec * self, GstCaps * caps)
   gint par_width, par_height;
   gboolean par_present;
 
+  GST_INFO_OBJECT (self, "set_caps (sink): %" GST_PTR_FORMAT, caps);
+
   s = gst_caps_get_structure (caps, 0);
   if (!klass->parse_caps (self, s)) {
     GST_WARNING_OBJECT (self, "missing required fields");
@@ -872,9 +1121,11 @@ gst_ducati_viddec_set_sink_caps (GstDucatiVidDec * self, GstCaps * caps)
       &par_width, &par_height);
 
   outcaps = gst_pad_get_allowed_caps (self->srcpad);
+  GST_DEBUG_OBJECT (self, "%s",
+      gst_caps_to_string (gst_pad_get_current_caps (self->srcpad)));
   if (outcaps) {
     outcaps = gst_caps_make_writable (outcaps);
-    gst_caps_truncate (outcaps);
+    outcaps = gst_caps_truncate (outcaps);
     if (gst_caps_is_empty (outcaps)) {
       gst_caps_unref (outcaps);
       outcaps = NULL;
@@ -882,8 +1133,8 @@ gst_ducati_viddec_set_sink_caps (GstDucatiVidDec * self, GstCaps * caps)
   }
 
   if (!outcaps) {
-    outcaps = gst_caps_new_simple ("video/x-raw-yuv",
-        "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('N', 'V', '1', '2'), NULL);
+    outcaps = gst_caps_new_simple ("video/x-raw",
+        "format", G_TYPE_STRING, "NV12", NULL);
   }
 
   out_s = gst_caps_get_structure (outcaps, 0);
@@ -898,11 +1149,13 @@ gst_ducati_viddec_set_sink_caps (GstDucatiVidDec * self, GstCaps * caps)
   if (self->interlaced)
     gst_structure_set (out_s, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL);
 
-  self->stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_NV12,
-      0, self->padded_width);
+  gst_structure_set (out_s, "drm_mem", G_TYPE_BOOLEAN, TRUE, NULL);
 
-  self->outsize = gst_video_format_get_size (GST_VIDEO_FORMAT_NV12,
-      self->stride, self->padded_height);
+  self->stride = GST_ROUND_UP_4 (self->padded_width);
+
+  self->outsize =
+      GST_ROUND_UP_4 (self->stride) * GST_ROUND_UP_2 (self->padded_height) * 3 /
+      2;
 
   GST_INFO_OBJECT (self, "outsize %d stride %d outcaps: %" GST_PTR_FORMAT,
       self->outsize, self->stride, outcaps);
@@ -916,8 +1169,6 @@ gst_ducati_viddec_set_sink_caps (GstDucatiVidDec * self, GstCaps * caps)
     gst_ducati_viddec_codec_flush (self, FALSE);
   }
 
-  /* (re)send a crop event when caps change */
-  self->send_crop_event = TRUE;
 
   ret = gst_pad_set_caps (self->srcpad, outcaps);
 
@@ -926,6 +1177,12 @@ gst_ducati_viddec_set_sink_caps (GstDucatiVidDec * self, GstCaps * caps)
   /* default to no reordering */
   self->backlog_maxframes = 0;
 
+  if (ret == TRUE) {
+    if (self->sinkcaps)
+      gst_caps_unref (self->sinkcaps);
+    self->sinkcaps = gst_caps_copy (caps);
+  }
+
 out:
   if (outcaps)
     gst_caps_unref (outcaps);
@@ -942,7 +1199,12 @@ gst_ducati_viddec_sink_setcaps (GstPad * pad, GstCaps * caps)
 
   GST_INFO_OBJECT (self, "setcaps (sink): %" GST_PTR_FORMAT, caps);
 
-  ret = klass->set_sink_caps (self, caps);
+  if (!self->sinkcaps || !gst_caps_is_strictly_equal (self->sinkcaps, caps))
+    ret = klass->set_sink_caps (self, caps);
+  else {
+    ret = TRUE;
+    gst_caps_unref (caps);
+  }
 
   gst_object_unref (self);
 
@@ -954,11 +1216,13 @@ gst_ducati_viddec_src_getcaps (GstPad * pad)
 {
   GstCaps *caps = NULL;
 
-  caps = GST_PAD_CAPS (pad);
+  caps = gst_pad_get_current_caps (pad);
   if (caps == NULL) {
-    return gst_caps_copy (gst_pad_get_pad_template_caps (pad));
+    GstCaps *fil = gst_pad_get_pad_template_caps (pad);
+    GST_DEBUG ("filter caps = %s \n", gst_caps_to_string (fil));
+    return fil;
   } else {
-    return gst_caps_copy (caps);
+    return caps;
   }
 }
 
@@ -969,16 +1233,13 @@ gst_ducati_viddec_query (GstDucatiVidDec * self, GstPad * pad,
   gboolean res = TRUE;
 
   switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_BUFFERS:
-      GST_DEBUG_OBJECT (self, "min buffers: %d", self->min_buffers);
-      gst_query_set_buffers_count (query, self->min_buffers);
-
-      GST_DEBUG_OBJECT (self, "min dimensions: %dx%d",
-          self->padded_width, self->padded_height);
-      gst_query_set_buffers_dimensions (query,
-          self->padded_width, self->padded_height);
-      *forward = FALSE;
+    case GST_QUERY_CAPS:
+    {
+      GstCaps *filter;
+      filter = gst_ducati_viddec_src_getcaps (pad);
+      gst_query_set_caps_result (query, filter);
       break;
+    }
     case GST_QUERY_LATENCY:
     {
       gboolean live;
@@ -1022,16 +1283,16 @@ gst_ducati_viddec_query (GstDucatiVidDec * self, GstPad * pad,
 }
 
 static gboolean
-gst_ducati_viddec_src_query (GstPad * pad, GstQuery * query)
+gst_ducati_viddec_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   gboolean res = TRUE, forward = TRUE;
-  GstDucatiVidDec *self = GST_DUCATIVIDDEC (GST_OBJECT_PARENT (pad));
+  GstDucatiVidDec *self = GST_DUCATIVIDDEC (parent);
   GstDucatiVidDecClass *klass = GST_DUCATIVIDDEC_GET_CLASS (self);
 
   GST_DEBUG_OBJECT (self, "query: %" GST_PTR_FORMAT, query);
   res = klass->query (self, pad, query, &forward);
   if (res && forward)
-    res = gst_pad_query_default (pad, query);
+    res = gst_pad_query_default (pad, parent, query);
 
   return res;
 }
@@ -1052,7 +1313,7 @@ gst_ducati_viddec_do_qos (GstDucatiVidDec * self, GstBuffer * buf)
     self->wait_keyframe = FALSE;
   }
 
-  timestamp = GST_BUFFER_TIMESTAMP (buf);
+  timestamp = GST_BUFFER_PTS (buf);
   if (self->segment.format != GST_FORMAT_TIME ||
       self->qos_earliest_time == GST_CLOCK_TIME_NONE)
     goto no_qos;
@@ -1097,58 +1358,23 @@ gst_ducati_viddec_can_drop_frame (GstDucatiVidDec * self, GstBuffer * buf,
   return FALSE;
 }
 
-GstElement *parser = NULL;
-
 static GstFlowReturn
-gst_ducati_viddec_chain (GstPad * pad, GstBuffer * buf)
+gst_ducati_viddec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
 {
-  GstElement *element = NULL;
-  GstElement *pipe = NULL;
-  GstPad *mypad = NULL;
-  GstPad *peerpad = NULL;
-  GstElement *peerelement = NULL;
   SizeT fd;
 
-  GstDucatiVidDec *self = GST_DUCATIVIDDEC (GST_OBJECT_PARENT (pad));
-  GstClockTime ts = GST_BUFFER_TIMESTAMP (buf);
+  GstDucatiVidDec *self = GST_DUCATIVIDDEC (parent);
+  GstClockTime ts = GST_BUFFER_PTS (buf);
   GstFlowReturn ret = GST_FLOW_OK;
   Int32 err;
   GstBuffer *outbuf = NULL;
   GstCaps *outcaps = NULL;
   gboolean decode;
 
-  element = gst_pad_get_parent_element (pad);
-  pipe = GST_ELEMENT (gst_element_get_parent (element));
-  mypad = gst_element_get_static_pad (element, "sink");
-  peerpad = gst_pad_get_peer (mypad);
-  peerelement = gst_pad_get_parent_element (peerpad);
-  if (parser == NULL)
-    {
-      parser = gst_element_factory_make ("jpegparse", NULL);
-      if (parser == NULL)
-       {
-         goto normal;
-       }
-      if (gst_bin_add (GST_BIN (pipe), parser) == FALSE)
-       {
-         gst_object_unref (parser);
-         parser = NULL;
-         goto normal;
-       }
-      gst_element_set_state (parser, GST_STATE_PAUSED);
-      gst_element_unlink (peerelement, element);
-      gst_element_link (parser, element);
-      if (FALSE == gst_element_link (peerelement, parser))
-       {
-         gst_element_set_state (parser, GST_STATE_NULL);
-         gst_element_unlink (parser, element);
-         gst_element_link (peerelement, element);
-         gst_bin_remove (GST_BIN (pipe), parser);
-         goto normal;
-       }
-      gst_pad_chain (gst_element_get_static_pad (parser, "sink"), buf);
-      return GST_FLOW_OK;
-    }
+  GstQuery *query = NULL;
+  guint min = 0;
+  guint max = 0;
+  guint size = 0;
 
 normal:
   if (G_UNLIKELY (!self->engine)) {
@@ -1158,7 +1384,7 @@ normal:
   }
 
   GST_DEBUG_OBJECT (self, "chain: %" GST_TIME_FORMAT " (%d bytes, flags %d)",
-      GST_TIME_ARGS (ts), GST_BUFFER_SIZE (buf), GST_BUFFER_FLAGS (buf));
+      GST_TIME_ARGS (ts), gst_buffer_get_size (buf), GST_BUFFER_FLAGS (buf));
 
   decode = gst_ducati_viddec_do_qos (self, buf);
   if (!decode) {
@@ -1172,39 +1398,14 @@ normal:
   /* do this before creating codec to ensure reverse caps negotiation
    * happens first:
    */
-allocate_buffer:
-  ret = gst_pad_alloc_buffer (self->srcpad, 0, self->outsize,
-      GST_PAD_CAPS (self->srcpad), &outbuf);
-  if (ret != GST_FLOW_OK) {
-    GST_WARNING_OBJECT (self, "alloc_buffer failed %s",
-        gst_flow_get_name (ret));
-    gst_buffer_unref (buf);
-    return ret;
-  }
-
-  outcaps = GST_BUFFER_CAPS (outbuf);
-  if (outcaps && !gst_caps_is_equal (outcaps, GST_PAD_CAPS (self->srcpad))) {
-    GstStructure *s;
-
-    GST_INFO_OBJECT (self, "doing upstream negotiation bufsize %d",
-        GST_BUFFER_SIZE (outbuf));
-
-    s = gst_caps_get_structure (outcaps, 0);
-    gst_structure_get_int (s, "rowstride", &self->stride);
-    self->outsize = gst_video_format_get_size (GST_VIDEO_FORMAT_NV12,
-        self->stride, self->padded_height);
-
-    GST_INFO_OBJECT (self, "outsize %d stride %d outcaps: %" GST_PTR_FORMAT,
-        self->outsize, self->stride, outcaps);
 
-    gst_pad_set_caps (self->srcpad, outcaps);
+allocate_buffer:
+  outbuf = codec_buffer_pool_get (self, NULL);
 
-    if (GST_BUFFER_SIZE (outbuf) != self->outsize) {
-      GST_INFO_OBJECT (self, "dropping buffer (bufsize %d != outsize %d)",
-          GST_BUFFER_SIZE (outbuf), self->outsize);
-      gst_buffer_unref (outbuf);
-      goto allocate_buffer;
-    }
+  if (outbuf == NULL) {
+    GST_WARNING_OBJECT (self, "alloc_buffer failed");
+    gst_buffer_unref (buf);
+    return GST_FLOW_ERROR;
   }
 
   if (G_UNLIKELY (!self->codec)) {
@@ -1216,7 +1417,7 @@ allocate_buffer:
     }
   }
 
-  GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
+  GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buf);
   GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
 
   /* Pass new output buffer to the decoder to decode into. Use buffers from the
@@ -1311,8 +1512,8 @@ have_out_buf:
 
   if (buf) {
     GST_DEBUG_OBJECT (self, "found remaining data: %d bytes",
-        GST_BUFFER_SIZE (buf));
-    ts = GST_BUFFER_TIMESTAMP (buf);
+        gst_buffer_get_size (buf));
+    ts = GST_BUFFER_PTS (buf);
     goto allocate_buffer;
   }
 
@@ -1323,30 +1524,33 @@ have_out_buf:
 }
 
 static gboolean
-gst_ducati_viddec_event (GstPad * pad, GstEvent * event)
+gst_ducati_viddec_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
-  GstDucatiVidDec *self = GST_DUCATIVIDDEC (GST_OBJECT_PARENT (pad));
+  GstDucatiVidDec *self = GST_DUCATIVIDDEC (parent);
   gboolean ret = TRUE;
 
   GST_DEBUG_OBJECT (self, "begin: event=%s", GST_EVENT_TYPE_NAME (event));
 
   switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_CAPS:
     {
-      gboolean update;
-      GstFormat fmt;
-      gint64 start, stop, time;
-      gdouble rate, arate;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &fmt,
-          &start, &stop, &time);
-      gst_segment_set_newsegment_full (&self->segment, update,
-          rate, arate, fmt, start, stop, time);
+      GstCaps *caps;
+      gst_event_parse_caps (event, &caps);
+      gst_event_unref (event);
+      return gst_ducati_viddec_sink_setcaps (pad, caps);
+      break;
+    }
+    case GST_EVENT_SEGMENT:
+    {
+
+      gst_event_copy_segment (event, &self->segment);
+
       break;
     }
     case GST_EVENT_EOS:
       if (!gst_ducati_viddec_codec_flush (self, TRUE)) {
         GST_ERROR_OBJECT (self, "could not flush on eos");
+        gst_event_unref (event);
         ret = FALSE;
       }
       break;
@@ -1373,9 +1577,9 @@ gst_ducati_viddec_event (GstPad * pad, GstEvent * event)
 }
 
 static gboolean
-gst_ducati_viddec_src_event (GstPad * pad, GstEvent * event)
+gst_ducati_viddec_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
-  GstDucatiVidDec *self = GST_DUCATIVIDDEC (GST_OBJECT_PARENT (pad));
+  GstDucatiVidDec *self = GST_DUCATIVIDDEC (parent);
   gboolean ret = TRUE;
 
   GST_LOG_OBJECT (self, "begin: event=%s", GST_EVENT_TYPE_NAME (event));
@@ -1386,8 +1590,9 @@ gst_ducati_viddec_src_event (GstPad * pad, GstEvent * event)
       gdouble proportion;
       GstClockTimeDiff diff;
       GstClockTime timestamp;
+      GstQOSType type;
 
-      gst_event_parse_qos (event, &proportion, &diff, &timestamp);
+      gst_event_parse_qos (event, &type, &proportion, &diff, &timestamp);
 
       GST_OBJECT_LOCK (self);
       self->qos_proportion = proportion;
@@ -1451,7 +1656,6 @@ gst_ducati_viddec_change_state (GstElement * element, GstStateChange transition)
   switch (transition) {
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       self->interlaced = FALSE;
-      self->send_crop_event = TRUE;
       gst_ducati_viddec_codec_flush (self, FALSE);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
@@ -1550,13 +1754,24 @@ gst_ducati_viddec_finalize (GObject * obj)
   GstDucatiVidDec *self = GST_DUCATIVIDDEC (obj);
 
   codec_delete (self);
+
+  if (self->sinkcaps)
+    gst_caps_unref (self->sinkcaps);
+
+  if (self->pool) {
+    gst_object_unref (self->pool);
+    self->pool = NULL;
+  }
+
   engine_close (self);
 
   /* Will unref the remaining buffers if needed */
+  g_hash_table_unref (self->dce_locked_bufs);
   g_hash_table_unref (self->passed_in_bufs);
-  if (self->codec_data) {
-    gst_buffer_unref (self->codec_data);
-    self->codec_data = NULL;
+
+  if (self->codecdata) {
+    g_slice_free1 (self->codecdatasize, self->codecdata);
+    self->codecdata = NULL;
   }
 
   G_OBJECT_CLASS (parent_class)->finalize (obj);
@@ -1576,6 +1791,7 @@ gst_ducati_viddec_class_init (GstDucatiVidDecClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+  parent_class = g_type_class_peek_parent (klass);
 
   gobject_class->get_property =
       GST_DEBUG_FUNCPTR (gst_ducati_viddec_get_property);
@@ -1621,7 +1837,7 @@ gst_ducati_viddec_class_init (GstDucatiVidDecClass * klass)
 }
 
 static void
-gst_ducati_viddec_init (GstDucatiVidDec * self, GstDucatiVidDecClass * klass)
+gst_ducati_viddec_init (GstDucatiVidDec * self, gpointer klass)
 {
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
 
@@ -1630,20 +1846,12 @@ gst_ducati_viddec_init (GstDucatiVidDec * self, GstDucatiVidDecClass * klass)
   self->sinkpad =
       gst_pad_new_from_template (gst_element_class_get_pad_template
       (gstelement_class, "sink"), "sink");
-  gst_pad_set_setcaps_function (self->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ducati_viddec_sink_setcaps));
-  gst_pad_set_chain_function (self->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ducati_viddec_chain));
-  gst_pad_set_event_function (self->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_ducati_viddec_event));
+  gst_pad_set_chain_function (self->sinkpad, gst_ducati_viddec_chain);
+  gst_pad_set_event_function (self->sinkpad, gst_ducati_viddec_event);
 
   self->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
-  gst_pad_set_event_function (self->srcpad,
-      GST_DEBUG_FUNCPTR (gst_ducati_viddec_src_event));
-  gst_pad_set_query_function (self->srcpad,
-      GST_DEBUG_FUNCPTR (gst_ducati_viddec_src_query));
-  gst_pad_set_getcaps_function (self->srcpad,
-      GST_DEBUG_FUNCPTR (gst_ducati_viddec_src_getcaps));
+  gst_pad_set_event_function (self->srcpad, gst_ducati_viddec_src_event);
+  gst_pad_set_query_function (self->srcpad, gst_ducati_viddec_src_query);
 
   gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
   gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
@@ -1659,9 +1867,8 @@ gst_ducati_viddec_init (GstDucatiVidDec * self, GstDucatiVidDecClass * klass)
   self->fps_d = -1;
 
   self->first_in_buffer = TRUE;
-  self->first_out_buffer = TRUE;
+  self->first_out_buffer = FALSE;
   self->interlaced = FALSE;
-  self->send_crop_event = TRUE;
 
 #ifdef USE_DTS_PTS_CODE
   self->dts_ridx = self->dts_widx = 0;
@@ -1670,8 +1877,13 @@ gst_ducati_viddec_init (GstDucatiVidDec * self, GstDucatiVidDecClass * klass)
   self->ts_is_pts = FALSE;
 #endif
 
+  self->codec_create_params_changed = FALSE;
+
   self->pageMemType = XDM_MEMTYPE_TILEDPAGE;
 
+  self->codecdata = NULL;
+  self->codecdatasize = 0;
+
   gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
 
   self->qos_proportion = 1;
@@ -1682,12 +1894,16 @@ gst_ducati_viddec_init (GstDucatiVidDec * self, GstDucatiVidDecClass * klass)
   self->device = NULL;
   self->input_bo = NULL;
 
+  self->sinkcaps = NULL;
+
   self->backlog_maxframes = 0;
   self->backlog_nframes = 0;
   self->backlog_max_maxframes = MAX_BACKLOG_FRAMES;
 
   self->codec_debug_info = FALSE;
 
+  self->dce_locked_bufs = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+      NULL, (GDestroyNotify) do_dce_buf_unlock);
   self->passed_in_bufs = g_hash_table_new_full (g_direct_hash, g_direct_equal,
       NULL, (GDestroyNotify) gst_buffer_unref);
 }