Changes for reverse playback
authorHarinarayan Bhatta <harinarayan@ti.com>
Fri, 4 Jul 2014 10:18:35 +0000 (15:48 +0530)
committerHarinarayan Bhatta <harinarayan@ti.com>
Fri, 4 Jul 2014 10:18:35 +0000 (15:48 +0530)
Adapt the re-order buffer to send out frames in reverse order
when playing with negative rate.

Signed-off-by: Harinarayan Bhatta <harinarayan@ti.com>
src/gstducatividdec.c
src/gstducatividdec.h

index 56ba4c3eac9c2cce83b6c37e67f81005763ad4a5..bd485d899288681713390df1cbf3051f2d1985ef 100644 (file)
@@ -347,6 +347,22 @@ codec_unlock_outbuf (GstDucatiVidDec * self, XDAS_Int32 id)
   }
 }
 
+/* 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 +394,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);
+    }
   }
 }
 
@@ -406,10 +431,11 @@ codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush,
          /* 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 */
+         GST_DEBUG_OBJECT (self, "dce_buf_lock(inputID: %08x", self->inArgs->inputID);
          dce_buf_lock(1,&fd);
   }
 
-  GST_DEBUG ("Calling VIDDEC3_process");
+  GST_DEBUG_OBJECT (self, "Calling VIDDEC3_process, inputID: %08x", self->inArgs->inputID);
   t = gst_util_get_timestamp ();
   err = VIDDEC3_process (self->codec,
       self->inBufs, self->outBufs, self->inArgs, self->outArgs);
@@ -449,6 +475,8 @@ codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush,
   for (i = 0; i < IVIDEO2_MAX_IO_BUFFERS && self->outArgs->outputID[i]; i++) {
     gboolean interlaced;
 
+    GST_DEBUG_OBJECT (self, "VIDDEC3_process outputID[%d]: %08x",
+               i, self->outArgs->outputID[i]);
     interlaced =
         self->outArgs->displayBufs.bufDesc[0].contentType ==
         IVIDEO_PROGRESSIVE ? FALSE : TRUE;
@@ -605,6 +633,8 @@ 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]);
   }
 
@@ -822,23 +852,51 @@ 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_TIMESTAMP (self->backlog_frames[0]) >
+            GST_BUFFER_TIMESTAMP (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;
 }
 
index 192d17a26c1f64c4405a9797181e13a94bfb11d4..6c7b9a54d798099efe4b384bd195a46e74be6ab9 100644 (file)
@@ -44,7 +44,10 @@ G_BEGIN_DECLS
 typedef struct _GstDucatiVidDec      GstDucatiVidDec;
 typedef struct _GstDucatiVidDecClass GstDucatiVidDecClass;
 
+/* For re-ordering in normal playback */
 #define MAX_BACKLOG_FRAMES 16
+/* For re-ordering in reverse playback */
+#define MAX_BACKLOG_ARRAY_SIZE 120
 
 struct _GstDucatiVidDec
 {
@@ -139,7 +142,7 @@ struct _GstDucatiVidDec
   struct omap_device *device;
 
   /* Frames waiting to be reordered */
-  GstBuffer *backlog_frames[MAX_BACKLOG_FRAMES + 1];
+  GstBuffer *backlog_frames[MAX_BACKLOG_ARRAY_SIZE + 1];
   gint backlog_maxframes;
   gint backlog_nframes;
   gint backlog_max_maxframes;