From c2dba3dbd209b10e9ede95983defed4e496bc5d3 Mon Sep 17 00:00:00 2001
From: Jeegar Patel <jeegarp@xilinx.com>
Date: Wed, 25 Jan 2017 20:17:04 +0530
Subject: [PATCH 17/24] Add event for transcode usecase

- Custom event handling is added in between decoder
  and encoder for sharing list of fds in pause->playing state

- Now we do not need to drop frames in transcode

Signed-off-by: Jeegar Patel <jeegarp@xilinx.com>
Upstream Status: Pending
---
 omx/gstomx.c         |   5 +-
 omx/gstomxvideodec.c |  24 +++++++---
 omx/gstomxvideoenc.c | 130 +++++++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 138 insertions(+), 21 deletions(-)

diff --git a/omx/gstomx.c b/omx/gstomx.c
index ccfeec8..9b7f1eb 100644
--- a/omx/gstomx.c
+++ b/omx/gstomx.c
@@ -1637,6 +1637,8 @@ gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port,
       err =
           OMX_UseBuffer (comp->handle, &buf->omx_buf, port->index, buf,
           port->port_def.nBufferSize, l->data);
+      if (port->index == 0)
+        printf ("Encoder i/p OMX_Usebuffer %d\n", buf->omx_buf->pBuffer);
       buf->eglimage = FALSE;
     } else if (images) {
       err =
@@ -1647,6 +1649,8 @@ gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port,
       err =
           OMX_AllocateBuffer (comp->handle, &buf->omx_buf, port->index, buf,
           port->port_def.nBufferSize);
+      if (port->index == 1)
+        printf ("Decoder o/p OMX_AllocateBuffer %d\n", buf->omx_buf->pBuffer);
       buf->eglimage = FALSE;
     }
 
@@ -1660,7 +1664,6 @@ gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port,
 
     GST_DEBUG_OBJECT (comp->parent, "%s: allocated buffer %p (%p)",
         comp->name, buf, buf->omx_buf->pBuffer);
-
     g_assert (buf->omx_buf->pAppPrivate == buf);
 
     /* In the beginning all buffers are not owned by the component */
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
index 38bb196..7383ab6 100644
--- a/omx/gstomxvideodec.c
+++ b/omx/gstomxvideodec.c
@@ -25,7 +25,7 @@
 #endif
 
 #include <gst/gst.h>
-
+#include<gst/gstevent.h>
 #if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__)
 #ifndef __VCCOREVER__
 #define __VCCOREVER__ 0x04000000
@@ -213,7 +213,7 @@ gst_omx_video_dec_open (GstVideoDecoder * decoder)
       (OMX_STRING) "OMX.allegro.linux.enableDMA", &DMAtype);
 
   memset (&enable_dmabuf, 0, sizeof (enable_dmabuf));
-  enable_dmabuf.nSize = sizeof(enable_dmabuf);
+  enable_dmabuf.nSize = sizeof (enable_dmabuf);
   enable_dmabuf.nVersion.s.nVersionMajor = OMXIL_MAJOR_VERSION;
   enable_dmabuf.nVersion.s.nVersionMinor = OMXIL_MINOR_VERSION;
   enable_dmabuf.nVersion.s.nRevision = OMXIL_REVISION;
@@ -944,8 +944,8 @@ gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self)
   }
 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
   err =
-      gst_omx_port_deallocate_buffers (self->eglimage ? self->
-      egl_out_port : self->dec_out_port);
+      gst_omx_port_deallocate_buffers (self->
+      eglimage ? self->egl_out_port : self->dec_out_port);
 #else
   err = gst_omx_port_deallocate_buffers (self->dec_out_port);
 #endif
@@ -1191,6 +1191,18 @@ enable_port:
   if (err != OMX_ErrorNone)
     goto done;
 
+  GstStructure *dmaList = gst_structure_new ("dmaStruct",
+      "dmaPtrArray", G_TYPE_POINTER, port->buffers, NULL);
+
+  GstEvent *dmaListEvent = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
+      dmaList);
+  GstPad *newpad = gst_element_get_static_pad (GST_ELEMENT (self), "src");
+  if (newpad == NULL)
+    printf ("src pad did not found\n");
+
+  gst_pad_push_event (newpad, dmaListEvent);
+
+
   err = gst_omx_port_populate (port);
   if (err != OMX_ErrorNone)
     goto done;
@@ -1342,8 +1354,8 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
           OMX_VIDEO_CodingUnused);
 
       format =
-          gst_omx_video_get_format_from_omx (port_def.format.video.
-          eColorFormat);
+          gst_omx_video_get_format_from_omx (port_def.format.
+          video.eColorFormat);
 
       if (format == GST_VIDEO_FORMAT_UNKNOWN) {
         GST_ERROR_OBJECT (self, "Unsupported color format: %d",
diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c
index 77c3f86..c7fb0db 100644
--- a/omx/gstomxvideoenc.c
+++ b/omx/gstomxvideoenc.c
@@ -112,6 +112,9 @@ static GstFlowReturn gst_omx_video_enc_drain (GstOMXVideoEnc * self,
 static GstFlowReturn gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc *
     self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
 
+static gboolean *gst_omx_video_enc_sink_event (GstVideoEncoder * encoder,
+    GstEvent * event);
+
 enum
 {
   PROP_0,
@@ -141,6 +144,11 @@ enum
 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXVideoEnc, gst_omx_video_enc,
     GST_TYPE_VIDEO_ENCODER, DEBUG_INIT);
 
+gboolean (*sink_event_backup) (GstVideoEncoder * encoder, GstEvent * event);
+GList *buffer_list = NULL;
+gint g_dmalist_count = 0;
+gint bufpool_complete = 0;
+
 static void
 gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
 {
@@ -219,6 +227,9 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
   video_encoder_class->propose_allocation =
       GST_DEBUG_FUNCPTR (gst_omx_video_enc_propose_allocation);
   video_encoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_omx_video_enc_getcaps);
+  sink_event_backup = video_encoder_class->sink_event;
+  video_encoder_class->sink_event =
+      GST_DEBUG_FUNCPTR (gst_omx_video_enc_sink_event);
 
   klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
   klass->cdata.default_sink_template_caps = "video/x-raw, "
@@ -1385,9 +1396,12 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf,
     }
 
     if (self->input_mode == OMX_Enc_InputMode_DMABufImport) {
-      outbuf->omx_buf->pBuffer =
-          gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (inbuf, 0));
-      printf ("Stride matches & Passed fd to OMX is %d\n",
+      //outbuf->omx_buf->pBuffer =
+      //    gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (inbuf, 0));
+      //printf ("Stride matches & Passed fd to OMX is %d\n",
+      //    outbuf->omx_buf->pBuffer);
+      printf ("Stride matches,Decoder o/p FD is %d, Encoder o/p FD is %d\n",
+          gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (inbuf, 0)),
           outbuf->omx_buf->pBuffer);
     }
 
@@ -1570,10 +1584,10 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
   GstOMXPort *port;
   GstOMXBuffer *buf;
   OMX_ERRORTYPE err;
-  GList *buffer_list = NULL;
   static gint count = 0;
-  static gint fd1 = 0, fd2 = 0;
-
+  gint fd1 = 0, fd2 = 0;
+  static GList *garray = NULL;
+  gint i;
   self = GST_OMX_VIDEO_ENC (encoder);
 
   GST_DEBUG_OBJECT (self, "Handling frame");
@@ -1594,25 +1608,70 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
 
   if (self->input_mode == OMX_Enc_InputMode_DMABufImport) {
     count++;
-    if (count == 1) {
+    if ((count == 1) && (bufpool_complete == 0)) {
       fd1 =
           gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (frame->input_buffer,
               0));
+      printf ("Got 1st fd %d\n", fd1);
+      garray = g_list_append (garray, fd1);
       frame->output_buffer = NULL;
       gst_video_encoder_finish_frame (self, frame);
       return self->downstream_flow_ret;
     }
-
-    if (count == 2) {
-      fd2 =
+    if (bufpool_complete == 0) {
+      fd1 =
           gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (frame->input_buffer,
               0));
+      printf ("Got next fd %d\n", fd1);
+      if (g_list_find (garray, fd1) != NULL) {
+        printf ("Bufferpool found completed \n");
+        bufpool_complete = 1;
+      } else {
+        garray = g_list_append (garray, fd1);
+        frame->output_buffer = NULL;
+        gst_video_encoder_finish_frame (self, frame);
+        return self->downstream_flow_ret;
+      }
+    }
+    if (bufpool_complete == 1) {
+
+      if (count == 1) {
+        printf ("Bufferpool found by event, It has %d buffers \n",
+            g_dmalist_count);
+        bufpool_complete = 2;
+        buffer_list = g_list_reverse (buffer_list);
+
+        gst_omx_port_update_port_definition (self->enc_in_port, NULL);
+        printf ("OMX Encoder BuffercountActual is %d\n",
+            self->enc_in_port->port_def.nBufferCountActual);
+        self->enc_in_port->port_def.nBufferCountActual = g_dmalist_count;
+        gst_omx_port_update_port_definition (self->enc_in_port,
+            &self->enc_in_port->port_def);
+        printf ("Updated OMX Encoder BuffercountActual is %d\n",
+            self->enc_in_port->port_def.nBufferCountActual);
+
 
-      gst_omx_port_update_port_definition (self->enc_in_port, NULL);
+      } else {
+
+        printf ("Bufferpool found by fd tracing, It has %d buffers \n",
+            g_list_length (garray));
+        bufpool_complete = 2;
+
+        for (i = 0; i < g_list_length (garray); i++)
+          buffer_list =
+              g_list_append (buffer_list,
+              GPOINTER_TO_INT (g_list_nth_data (garray, i)));
+
+        gst_omx_port_update_port_definition (self->enc_in_port, NULL);
+        printf ("OMX Encoder BuffercountActual is %d\n",
+            self->enc_in_port->port_def.nBufferCountActual);
+        self->enc_in_port->port_def.nBufferCountActual = g_list_length (garray);
+        gst_omx_port_update_port_definition (self->enc_in_port,
+            &self->enc_in_port->port_def);
+        printf ("Updated OMX Encoder BuffercountActual is %d\n",
+            self->enc_in_port->port_def.nBufferCountActual);
 
-      //TODO: Currently we know, V4l2src bufferpool has 2 fds, But we need to make it dynamic */
-      buffer_list = g_list_append (buffer_list, fd2);
-      buffer_list = g_list_append (buffer_list, fd1);
+      }
 
       if (gst_omx_port_use_buffers (self->enc_in_port,
               buffer_list) != OMX_ErrorNone)
@@ -1912,6 +1971,49 @@ gst_omx_video_enc_drain (GstOMXVideoEnc * self, gboolean at_eos)
   return GST_FLOW_OK;
 }
 
+static void
+test_data (GstOMXBuffer * buf)
+{
+  buffer_list = g_list_append (buffer_list, buf->omx_buf->pBuffer);
+  g_dmalist_count++;
+  return;
+}
+
+static gboolean *
+gst_omx_video_enc_sink_event (GstVideoEncoder * encoder, GstEvent * event)
+{
+  GstOMXVideoEnc *self;
+
+  self = GST_OMX_VIDEO_ENC (encoder);
+  GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  const GValue *p;
+  struct GPtrArray *buffers;
+  gint value;
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CUSTOM_DOWNSTREAM:{
+      const GstStructure *structure = gst_event_get_structure (event);
+
+      if (gst_structure_has_name (structure, "dmaStruct")) {
+        p = gst_structure_get_value (structure, "dmaPtrArray");
+        buffers = g_value_get_pointer (p);
+        g_ptr_array_foreach (buffers, test_data, NULL);
+        bufpool_complete = 1;
+        printf ("Custom event for DMA list is sucessful, got %d fd \n",
+            g_dmalist_count);
+      }
+      return sink_event_backup (encoder, event);
+      break;
+    }
+    default:
+      return sink_event_backup (encoder, event);
+      break;
+  }
+
+  return 0;
+}
+
 static gboolean
 gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
     GstQuery * query)
-- 
2.7.4

