Merge tizen patch based on 1.12.2
[platform/upstream/gstreamer.git] / omx / gstomxvideodec.c
index 7082bb8..d04daf7 100755 (executable)
@@ -46,6 +46,7 @@
 #pragma GCC diagnostic pop
 #endif
 
+//#define CODEC_DEC_INTPUT_DUMP
 //#define CODEC_DEC_OUTPUT_DUMP
 #include <stdio.h>
 #include <string.h>
@@ -84,6 +85,11 @@ static OMX_ERRORTYPE gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec *
 static OMX_ERRORTYPE gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec
     * self);
 
+#ifdef TIZEN_FEATURE_OMX
+static gboolean gst_omx_video_dec_acquire_request_flush_buffer (GstOMXVideoDec * self, GstBuffer ** flush_request_buffer);
+static gboolean gst_omx_video_dec_handle_event (GstVideoDecoder * decoder, GstEvent *event);
+#endif
+
 enum
 {
   PROP_0
@@ -124,6 +130,10 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
   video_decoder_class->decide_allocation =
       GST_DEBUG_FUNCPTR (gst_omx_video_dec_decide_allocation);
 
+#ifdef TIZEN_FEATURE_OMX
+  video_decoder_class->sink_event = GST_DEBUG_FUNCPTR (gst_omx_video_dec_handle_event);
+#endif
+
   klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
   klass->cdata.default_src_template_caps =
 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
@@ -132,7 +142,8 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
 #endif
       "video/x-raw, "
       "width = " GST_VIDEO_SIZE_RANGE ", "
-      "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE;
+         "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE ", "
+      "format = (string)SN12";
 }
 
 static void
@@ -146,8 +157,8 @@ gst_omx_video_dec_init (GstOMXVideoDec * self)
   g_mutex_init (&self->drain_lock);
   g_cond_init (&self->drain_cond);
 
-#ifdef GST_TIZEN_MODIFICATION
-  self->hTBMBufMgr = NULL;
+#ifdef TIZEN_FEATURE_OMX
+  self->bufmgr = NULL;
   self->drm_fd = -1;
 #endif
 }
@@ -199,20 +210,49 @@ gst_omx_video_dec_open (GstVideoDecoder * decoder)
       out_port_index = param.nStartPortNumber + 1;
     }
   }
+
   self->dec_in_port = gst_omx_component_add_port (self->dec, in_port_index);
   self->dec_out_port = gst_omx_component_add_port (self->dec, out_port_index);
 
   if (!self->dec_in_port || !self->dec_out_port)
     return FALSE;
 
-#ifdef GST_TIZEN_MODIFICATION
-
-   self->hTBMBufMgr = tbm_bufmgr_init(self->drm_fd);
-   if(self->hTBMBufMgr == NULL){
+#ifdef TIZEN_FEATURE_OMX
+  self->bufmgr = tbm_bufmgr_init(self->drm_fd);
+  if (self->bufmgr == NULL) {
     GST_ERROR_OBJECT (self, "TBM initialization failed.");
     return FALSE;
-   }
+  }
+
+#if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
+  {
+    /* set plateform specific gem buffer settings. */
+    OMX_ERRORTYPE err;
+    EnableGemBuffersParams gem_param;
+    OMX_INDEXTYPE index = OMX_IndexComponentStartUnused;
+
+    err = gst_omx_component_get_extension_index (self->dec, (OMX_STRING) EXYNOS_INDEX_PARAM_STORE_METADATA_BUFFER, &index);
+    if (err != OMX_ErrorNone) {
+      GST_WARNING_OBJECT (self, "Failed to get extension index : %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+    }
+
+    OMX_INIT_PARAM (gem_param);
+    gem_param.enable = OMX_TRUE;
+    gem_param.nPortIndex = 1;
+
+    err = gst_omx_component_set_parameter(self->dec, index, &gem_param);
+    if (err != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (self, "Failed to set platform specific buffer: %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+    }
+
+    self->dec_in_port->use_buffer = klass->cdata.in_port_usebuffer;
+    self->dec_out_port->use_buffer = klass->cdata.out_port_usebuffer;
+  }
 #endif
+#endif
+
   GST_DEBUG_OBJECT (self, "Opened decoder");
 
 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
@@ -293,7 +333,7 @@ gst_omx_video_dec_shutdown (GstOMXVideoDec * self)
     }
   }
 
-  /* Otherwise we didn't use EGL and just fall back to 
+  /* Otherwise we didn't use EGL and just fall back to
    * shutting down the decoder */
 #endif
 
@@ -310,11 +350,11 @@ gst_omx_video_dec_shutdown (GstOMXVideoDec * self)
       gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
   }
 
-#ifdef GST_TIZEN_MODIFICATION
+#ifdef TIZEN_FEATURE_OMX
    /* uninitialize tbm buffer manager */
-   if(self->hTBMBufMgr != NULL){
-    tbm_bufmgr_deinit(self->hTBMBufMgr);
-    self->hTBMBufMgr = NULL;
+   if(self->bufmgr != NULL){
+    tbm_bufmgr_deinit(self->bufmgr);
+    self->bufmgr = NULL;
    }
 
    if(self->drm_fd != -1) {
@@ -410,9 +450,6 @@ gst_omx_video_dec_change_state (GstElement * element, GstStateChange transition)
       break;
   }
 
-  if (ret == GST_STATE_CHANGE_FAILURE)
-    return ret;
-
   ret =
       GST_ELEMENT_CLASS (gst_omx_video_dec_parent_class)->change_state
       (element, transition);
@@ -439,6 +476,25 @@ gst_omx_video_dec_change_state (GstElement * element, GstStateChange transition)
   return ret;
 }
 
+#ifdef CODEC_DEC_INTPUT_DUMP /* for decoder input dump */
+static inline void
+decoder_input_dump (GstOMXBuffer * buf, gboolean use_buffer)
+{
+  gchar *temp;
+  gchar filename[100]={0};
+  FILE *fp = NULL;
+
+  temp = use_buffer ? buf->mm_vbuffer->data[0] : buf->omx_buf->pBuffer;
+
+  sprintf(filename, "/tmp/dec_input_dump.out");
+  fp = fopen(filename, "ab");
+
+  fwrite(temp, buf->omx_buf->nFilledLen, 1, fp);
+
+  fclose(fp);
+}
+#endif
+
 #ifdef CODEC_DEC_OUTPUT_DUMP /* for decoder output dump */
 static inline void
 decoder_output_dump(GstOMXVideoDec *self, MMVideoBuffer *outbuf)
@@ -451,7 +507,7 @@ decoder_output_dump(GstOMXVideoDec *self, MMVideoBuffer *outbuf)
 
   GST_ERROR_OBJECT (self, "codec dec output dump start. w = %d, h = %d", outbuf->width[0], outbuf->height[0]);
 
-  sprintf(filename, "/tmp/dec_output_dump_%d_%d.yuv", outbuf->stride_width[0], outbuf->height[0]);
+  sprintf(filename, "/tmp/dec_output_dump_%d_%d.yuv", outbuf->width[0], outbuf->height[0]);
   fp = fopen(filename, "ab");
 
   for (i = 0; i < outbuf->height[0]; i++) {
@@ -480,7 +536,9 @@ gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
   GstVideoInfo *vinfo = &state->info;
   OMX_PARAM_PORTDEFINITIONTYPE *port_def = &self->dec_out_port->port_def;
   gboolean ret = FALSE;
+#ifndef TIZEN_FEATURE_OMX
   GstVideoFrame frame;
+#endif
 
   if (vinfo->width != port_def->format.video.nFrameWidth ||
       vinfo->height != port_def->format.video.nFrameHeight) {
@@ -492,7 +550,7 @@ gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
   }
 
   /* Same strides and everything */
-#if 0  //ENS:a
+#ifndef TIZEN_FEATURE_OMX
   if (gst_buffer_get_size (outbuf) == inbuf->omx_buf->nFilledLen) {
     GstMapInfo map = GST_MAP_INFO_INIT;
 
@@ -511,102 +569,105 @@ gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
 #endif  //ENS:a
 
   /* Different strides */
+#ifndef TIZEN_FEATURE_OMX
   if (gst_video_frame_map (&frame, vinfo, outbuf, GST_MAP_WRITE)) {
-    const guint nstride = port_def->format.video.nStride;
-    const guint nslice = port_def->format.video.nSliceHeight;
-    guint src_stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
-    guint src_size[GST_VIDEO_MAX_PLANES] = { nstride * nslice, 0, };
-    gint dst_width[GST_VIDEO_MAX_PLANES] = { 0, };
-    gint dst_height[GST_VIDEO_MAX_PLANES] =
-        { GST_VIDEO_INFO_HEIGHT (vinfo), 0, };
-    const guint8 *src;
-    guint p;
-
-    switch (GST_VIDEO_INFO_FORMAT (vinfo)) {
-      case GST_VIDEO_FORMAT_ABGR:
-      case GST_VIDEO_FORMAT_ARGB:
-        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 4;
-        break;
-      case GST_VIDEO_FORMAT_RGB16:
-      case GST_VIDEO_FORMAT_BGR16:
-      case GST_VIDEO_FORMAT_YUY2:
-      case GST_VIDEO_FORMAT_UYVY:
-      case GST_VIDEO_FORMAT_YVYU:
-        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 2;
-        break;
-      case GST_VIDEO_FORMAT_GRAY8:
-        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
-        break;
-      case GST_VIDEO_FORMAT_I420:
-        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
-        src_stride[1] = nstride / 2;
-        src_size[1] = (src_stride[1] * nslice) / 2;
-        dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
-        dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
-        src_stride[2] = nstride / 2;
-        src_size[2] = (src_stride[1] * nslice) / 2;
-        dst_width[2] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
-        dst_height[2] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
-        break;
-      case GST_VIDEO_FORMAT_NV12:
-        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
-        src_stride[1] = nstride;
-        src_size[1] = src_stride[1] * nslice / 2;
-        dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
-        dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
-        break;
-      case GST_VIDEO_FORMAT_NV16:
-        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
-        src_stride[1] = nstride;
-        src_size[1] = src_stride[1] * nslice;
-        dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
-        dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo);
-        break;
-      case GST_VIDEO_FORMAT_SN12:
-      case GST_VIDEO_FORMAT_ST12:{
-        GstMemory *mem_imgb = NULL;
-        void *imgb_data = NULL;
-#ifdef GST_TIZEN_MODIFICATION
-        MMVideoBuffer *mm_vbuffer = NULL;
-        mm_vbuffer = (MMVideoBuffer*)(inbuf->omx_buf->pBuffer);
-        mm_vbuffer->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
-
-        if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
-          GST_LOG_OBJECT (self, "dec output buf: fd[0]:%d  fd[1]:%d fd[2]:%d  w[0]:%d h[0]:%d  buf_share_method:%d",
-                  mm_vbuffer->handle.dmabuf_fd[0], mm_vbuffer->handle.dmabuf_fd[1], mm_vbuffer->handle.dmabuf_fd[2],
-                  mm_vbuffer->width[0], mm_vbuffer->height[0], mm_vbuffer->type);
-        } else if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
-          GST_LOG_OBJECT (self, "dec output uses hw addr");
-        } else {
-          GST_WARNING_OBJECT (self, "dec output buf has TBM_BO buf_share_method");
-        }
+  const guint nstride = port_def->format.video.nStride;
+  const guint nslice = port_def->format.video.nSliceHeight;
+  guint src_stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
+  guint src_size[GST_VIDEO_MAX_PLANES] = { nstride * nslice, 0, };
+  gint dst_width[GST_VIDEO_MAX_PLANES] = { 0, };
+  gint dst_height[GST_VIDEO_MAX_PLANES] =
+      { GST_VIDEO_INFO_HEIGHT (vinfo), 0, };
+  const guint8 *src;
+  guint p;
+#endif
+
+  switch (GST_VIDEO_INFO_FORMAT (vinfo)) {
+#ifndef TIZEN_FEATURE_OMX
+    case GST_VIDEO_FORMAT_ABGR:
+    case GST_VIDEO_FORMAT_ARGB:
+      dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 4;
+      break;
+    case GST_VIDEO_FORMAT_RGB16:
+    case GST_VIDEO_FORMAT_BGR16:
+    case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_UYVY:
+    case GST_VIDEO_FORMAT_YVYU:
+      dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 2;
+      break;
+    case GST_VIDEO_FORMAT_GRAY8:
+      dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+      break;
+    case GST_VIDEO_FORMAT_I420:
+      dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+      src_stride[1] = nstride / 2;
+      src_size[1] = (src_stride[1] * nslice) / 2;
+      dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
+      dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
+      src_stride[2] = nstride / 2;
+      src_size[2] = (src_stride[1] * nslice) / 2;
+      dst_width[2] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
+      dst_height[2] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
+      break;
+    case GST_VIDEO_FORMAT_NV12:
+      dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+      src_stride[1] = nstride;
+      src_size[1] = src_stride[1] * nslice / 2;
+      dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
+      dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
+      break;
+    case GST_VIDEO_FORMAT_NV16:
+      dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+      src_stride[1] = nstride;
+      src_size[1] = src_stride[1] * nslice;
+      dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
+      dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo);
+      break;
+#endif
+#ifdef TIZEN_FEATURE_OMX
+    case GST_VIDEO_FORMAT_SN12:
+    case GST_VIDEO_FORMAT_ST12: {
+      GstMemory *mem = NULL;
+      void *data = NULL;
+      MMVideoBuffer *mm_vbuffer = NULL;
+      mm_vbuffer = (MMVideoBuffer*)(inbuf->omx_buf->pBuffer);
+
+      if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
+        GST_LOG_OBJECT (self, "dec output buf: bo[0] :%p, bo[1] : %p, fd[0]:%d  fd[1]:%d fd[2]:%d  w[0]:%d h[0]:%d  buf_share_method:%d",
+            mm_vbuffer->handle.bo[0], mm_vbuffer->handle.bo[1], mm_vbuffer->handle.dmabuf_fd[0], mm_vbuffer->handle.dmabuf_fd[1], mm_vbuffer->handle.dmabuf_fd[2],
+            mm_vbuffer->width[0], mm_vbuffer->height[0], mm_vbuffer->type);
+      } else if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
+        GST_LOG_OBJECT (self, "dec output uses hw addr");
+      } else {
+        GST_WARNING_OBJECT (self, "dec output buf has TBM_BO buf_share_method");
+      }
 #ifdef CODEC_DEC_OUTPUT_DUMP
-       decoder_output_dump(self, mm_vbuffer);
-#endif
-#endif
-        if (gst_buffer_n_memory(outbuf) < 2) {
-            imgb_data = g_malloc0(sizeof(*mm_vbuffer));
-            mem_imgb = gst_memory_new_wrapped(0, imgb_data, sizeof(*mm_vbuffer), 0, sizeof(*mm_vbuffer), imgb_data, g_free);
-            gst_buffer_append_memory(outbuf, mem_imgb);
-        } else {
-            GstMapInfo imgb_info = GST_MAP_INFO_INIT;
-            mem_imgb = gst_buffer_peek_memory(outbuf, 1);
-            gst_memory_map(mem_imgb, &imgb_info, GST_MAP_WRITE);
-            imgb_data = imgb_info.data;
-            gst_memory_unmap(mem_imgb, &imgb_info);
-        }
-#ifdef GST_TIZEN_MODIFICATION
-        memcpy(imgb_data, mm_vbuffer, sizeof(MMVideoBuffer));
+     decoder_output_dump(self, mm_vbuffer);
 #endif
-        ret = TRUE;
-        break;
+      if (gst_buffer_n_memory (outbuf) < 2) {
+        data = g_malloc0 (sizeof (MMVideoBuffer));
+        mem = gst_memory_new_wrapped (0, data, sizeof (MMVideoBuffer), 0, sizeof (MMVideoBuffer), data, g_free);
+        gst_buffer_append_memory (outbuf, mem);
+      } else {
+        GstMapInfo info = GST_MAP_INFO_INIT;
+
+        mem = gst_buffer_peek_memory (outbuf, 1);
+        gst_memory_map (mem, &info, GST_MAP_WRITE);
+        data = info.data;
+        gst_memory_unmap (mem, &info);
+      }
+      memcpy (data, mm_vbuffer, sizeof (MMVideoBuffer));
+
+      ret = TRUE;
+      break;
     }
+#endif
 
       default:
         g_assert_not_reached ();
         break;
     }
-
+#ifndef TIZEN_FEATURE_OMX
     src = inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset;
     for (p = 0; p < GST_VIDEO_INFO_N_PLANES (vinfo); p++) {
       const guint8 *data;
@@ -622,13 +683,16 @@ gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
       }
       src += src_size[p];
     }
+#endif
 
+#ifndef TIZEN_FEATURE_OMX
     gst_video_frame_unmap (&frame);
     ret = TRUE;
   } else {
     GST_ERROR_OBJECT (self, "Can't map output buffer to frame");
     goto done;
   }
+#endif
 
 done:
   if (ret) {
@@ -890,9 +954,8 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
       }
       was_enabled = FALSE;
     }
-#ifdef GST_TIZEN_MODIFICATION
-    err = gst_omx_port_tbm_allocate_dec_buffers(port, self->hTBMBufMgr,
-      self->dec_in_port->port_def.format.video.eCompressionFormat);
+#ifdef TIZEN_FEATURE_OMX
+    err = gst_omx_port_tbm_allocate_dec_buffers (port, self->bufmgr, port->use_buffer);
 #else
     err = gst_omx_port_allocate_buffers (port);
 #endif
@@ -926,9 +989,8 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
           goto done;
         }
       }
-#ifdef GST_TIZEN_MODIFICATION
-      err = gst_omx_port_tbm_allocate_dec_buffers(port, self->hTBMBufMgr,
-          self->dec_in_port->port_def.format.video.eCompressionFormat);
+#ifdef TIZEN_FEATURE_OMX
+      err = gst_omx_port_tbm_allocate_dec_buffers (port, self->bufmgr, port->use_buffer);
 #else
       err = gst_omx_port_allocate_buffers (port);
 #endif
@@ -1359,6 +1421,16 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
   GstOMXAcquireBufferReturn acq_return;
   GstClockTimeDiff deadline;
   OMX_ERRORTYPE err;
+#ifdef TIZEN_FEATURE_OMX
+  GstBuffer *flush_request_buffer = NULL;
+  GstMessage *msg = NULL;
+#endif
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  port = self->eglimage ? self->egl_out_port : self->dec_out_port;
+#else
+  port = self->dec_out_port;
+#endif
 
 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
   port = self->eglimage ? self->egl_out_port : self->dec_out_port;
@@ -1386,6 +1458,17 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
     /* Reallocate all buffers */
     if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE
         && gst_omx_port_is_enabled (port)) {
+#ifdef TIZEN_FEATURE_OMX
+      if (gst_omx_video_dec_acquire_request_flush_buffer (self, &flush_request_buffer)) {
+        flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), flush_request_buffer);
+
+        if (flow_ret != GST_FLOW_OK) {
+          gst_buffer_unref (flush_request_buffer);
+          flush_request_buffer = NULL;
+          goto reconfigure_error;
+        }
+      }
+#endif
       err = gst_omx_port_set_enabled (port, FALSE);
       if (err != OMX_ErrorNone)
         goto reconfigure_error;
@@ -1408,6 +1491,13 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
       err = gst_omx_video_dec_reconfigure_output_port (self);
       if (err != OMX_ErrorNone)
         goto reconfigure_error;
+#ifdef TIZEN_FEATURE_OMX
+      msg = gst_message_new_element (GST_OBJECT_CAST (self), gst_structure_new ("prepare-decode-buffers",
+                                 "num_buffers", G_TYPE_INT, self->dec_out_port->port_def.nBufferCountActual,
+                                 "extra_num_buffers", G_TYPE_INT, EXTRA_DECODER_OUTPUT_BUF, NULL));
+
+      gst_element_post_message (GST_ELEMENT_CAST (self), msg);
+#endif
     } else {
       /* Just update caps */
       GST_VIDEO_DECODER_STREAM_LOCK (self);
@@ -1533,7 +1623,6 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
             copy_frame (&GST_OMX_BUFFER_POOL (self->out_port_pool)->video_info,
             outbuf);
 
-      buf = NULL;
     } else {
       outbuf =
           gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));
@@ -1543,12 +1632,43 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
         goto invalid_buffer;
       }
     }
+#ifdef TIZEN_FEATURE_OMX
+    {
+      MMVideoBuffer *mm_vbuffer = NULL;
+      GstMemory *mem = NULL;
+      guint8 *data = NULL;
+      mm_vbuffer = (MMVideoBuffer*)(buf->omx_buf->pBuffer);
+
+      if (gst_buffer_n_memory (outbuf) < 2) {
+        data = g_malloc0 (sizeof (MMVideoBuffer));
+        mem = gst_memory_new_wrapped (0, data, sizeof(MMVideoBuffer), 0, sizeof(MMVideoBuffer), data, g_free);
+        gst_buffer_append_memory (outbuf, mem);
+      } else {
+        GstMapInfo info = GST_MAP_INFO_INIT;
+        mem = gst_buffer_peek_memory (outbuf, 1);
+        gst_memory_map (mem, &info, GST_MAP_WRITE);
+        data = info.data;
+        gst_memory_unmap (mem, &info);
+      }
+      memcpy(data, mm_vbuffer, sizeof(MMVideoBuffer));
+      buf = NULL;
 
+      if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
+        GST_LOG_OBJECT (self, "frame not found: bo[0] :%p, bo[1] : %p, fd[0]:%d  fd[1]:%d fd[2]:%d  w[0]:%d h[0]:%d  buf_share_method:%d",
+            mm_vbuffer->handle.bo[0], mm_vbuffer->handle.bo[1], mm_vbuffer->handle.dmabuf_fd[0], mm_vbuffer->handle.dmabuf_fd[1], mm_vbuffer->handle.dmabuf_fd[2],
+            mm_vbuffer->width[0], mm_vbuffer->height[0], mm_vbuffer->type);
+      } else if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
+        GST_LOG_OBJECT (self, "dec output uses hw addr");
+      } else {
+        GST_WARNING_OBJECT (self, "dec output buf has TBM_BO buf_share_method");
+      }
+    }
+#endif
     flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf);
   } else if (buf->omx_buf->nFilledLen > 0 || buf->eglimage) {
     if (self->out_port_pool) {
       gint i, n;
-      GstBuffer *outbuf;
+      GstBuffer *outbuf = NULL;
       GstBufferPoolAcquireParams params = { 0, };
 
       n = port->buffers->len;
@@ -1583,18 +1703,19 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
       frame = NULL;
       buf = NULL;
       } else {
-          if(!gst_omx_video_dec_fill_buffer (self, buf, frame->output_buffer)) {
-              gst_buffer_replace (&frame->output_buffer, NULL);
-              flow_ret =
-                  gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
-              frame = NULL;
-              gst_omx_port_release_buffer (port, buf);
-              goto invalid_buffer;
-          }
+        if (!gst_omx_video_dec_fill_buffer (self, buf, frame->output_buffer)) {
+          gst_buffer_replace (&frame->output_buffer, NULL);
+
           flow_ret =
-              gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
+              gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
           frame = NULL;
-          buf = NULL;
+          gst_omx_port_release_buffer (port, buf);
+          goto invalid_buffer;
+        }
+        flow_ret =
+            gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
+        frame = NULL;
+        buf = NULL;
       }
     } else {
       if ((flow_ret =
@@ -1657,9 +1778,15 @@ component_error:
 flushing:
   {
     GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+    g_mutex_lock (&self->drain_lock);
+    if (self->draining) {
+      self->draining = FALSE;
+      g_cond_broadcast (&self->drain_cond);
+    }
     gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
     self->downstream_flow_ret = GST_FLOW_FLUSHING;
     self->started = FALSE;
+    g_mutex_unlock (&self->drain_lock);
     return;
   }
 
@@ -1717,8 +1844,14 @@ flow_error:
       self->started = FALSE;
     } else if (flow_ret == GST_FLOW_FLUSHING) {
       GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+      g_mutex_lock (&self->drain_lock);
+      if (self->draining) {
+        self->draining = FALSE;
+        g_cond_broadcast (&self->drain_cond);
+      }
       gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
       self->started = FALSE;
+      g_mutex_unlock (&self->drain_lock);
     }
     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
     return;
@@ -1844,11 +1977,10 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
   GstCaps *templ_caps, *intersection;
   GstVideoFormat format;
   GstStructure *s;
-  const gchar *format_str;
-#ifdef GST_TIZEN_MODIFICATION
-  gchar *format_tmp;
+  const gchar *format_str = NULL;
+#ifdef TIZEN_FEATURE_OMX
+  const gchar *format_tmp;
   int i;
-  EnableGemBuffersParams gemBuffers;
 #endif
 
   GST_DEBUG_OBJECT (self, "Trying to negotiate a video format with downstream");
@@ -1884,19 +2016,21 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
     return FALSE;
   }
 
-  for(i=0; i<gst_caps_get_size(intersection); i++)
+#ifdef TIZEN_FEATURE_OMX
+  for(i = 0; i < gst_caps_get_size (intersection); i++)
   {
       s = gst_caps_get_structure (intersection, i);
-      format_tmp = gst_structure_get_string (s, "format");
+      if ((format_tmp = gst_structure_get_string (s, "format"))) {
 
-      if(!strncmp(format_tmp, "S", 1)) {
+        if (!strncmp (format_tmp, "S", 1)) {
           format_str = format_tmp;
           GST_DEBUG_OBJECT (self, "SEC format found");
           break;
+        }
       }
   }
 
-  if(!format_str) {
+  if (!format_str) {
     intersection = gst_caps_truncate (intersection);
     intersection = gst_caps_fixate (intersection);
 
@@ -1904,6 +2038,7 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
     format_str = gst_structure_get_string (s, "format");
     GST_DEBUG_OBJECT (self, "first structure will be fixated");
   }
+#endif
 
   if (!format_str ||
       (format =
@@ -1944,21 +2079,6 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
         gst_omx_error_to_string (err), err);
   }
 
-  /* set plateform specific gem buffer settings. */
-
-    /* Set platform specific buffer settings. to avoid plane support error.. */
-#ifdef GST_TIZEN_MODIFICATION
-    OMX_INIT_STRUCTURE(gemBuffers);
-    gemBuffers.enable = OMX_TRUE;
-    gemBuffers.nPortIndex = 1;
-      err =
-      gst_omx_component_set_parameter (self->dec,
-      OMX_IndexParamEnablePlatformSpecificBuffers,&gemBuffers);
-  if (err != OMX_ErrorNone) {
-    GST_ERROR_OBJECT (self, "Failed to set video port format: %s (0x%08x)",
-        gst_omx_error_to_string (err), err);
-  }
-#endif
   gst_caps_unref (intersection);
   return (err == OMX_ErrorNone);
 }
@@ -2034,6 +2154,9 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
       if (!gst_omx_video_dec_open (GST_VIDEO_DECODER (self)))
         return FALSE;
       needs_disable = FALSE;
+#ifdef TIZEN_FEATURE_OMX
+      gst_omx_port_get_port_definition (self->dec_in_port, &port_def);
+#endif
     } else {
 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
       if (self->eglimage) {
@@ -2043,27 +2166,33 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
         gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
       }
 #endif
-
       if (gst_omx_port_set_enabled (self->dec_in_port, FALSE) != OMX_ErrorNone)
         return FALSE;
-      if (gst_omx_port_set_enabled (out_port, FALSE) != OMX_ErrorNone)
-        return FALSE;
+
       if (gst_omx_port_wait_buffers_released (self->dec_in_port,
               5 * GST_SECOND) != OMX_ErrorNone)
         return FALSE;
-      if (gst_omx_port_wait_buffers_released (out_port,
-              1 * GST_SECOND) != OMX_ErrorNone)
-        return FALSE;
+
       if (gst_omx_port_deallocate_buffers (self->dec_in_port) != OMX_ErrorNone)
         return FALSE;
-      if (gst_omx_video_dec_deallocate_output_buffers (self) != OMX_ErrorNone)
-        return FALSE;
+
       if (gst_omx_port_wait_enabled (self->dec_in_port,
               1 * GST_SECOND) != OMX_ErrorNone)
         return FALSE;
-      if (gst_omx_port_wait_enabled (out_port, 1 * GST_SECOND) != OMX_ErrorNone)
+#ifndef TIZEN_FEATURE_OMX
+      if (gst_omx_port_set_enabled (out_port, FALSE) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_port_wait_buffers_released (out_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
         return FALSE;
 
+      if (gst_omx_video_dec_deallocate_output_buffers (self) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_port_wait_enabled (out_port, 1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+#endif
 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
       if (self->eglimage) {
         OMX_STATETYPE egl_state;
@@ -2136,14 +2265,15 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
   if (needs_disable) {
     if (gst_omx_port_set_enabled (self->dec_in_port, TRUE) != OMX_ErrorNone)
       return FALSE;
-#ifdef GST_TIZEN_MODIFICATION
-    if(gst_omx_port_tbm_allocate_dec_buffers(self->dec_in_port, self->hTBMBufMgr, 0) != OMX_ErrorNone)
+#ifdef TIZEN_FEATURE_OMX
+    if (gst_omx_port_tbm_allocate_dec_buffers (self->dec_in_port,
+        self->bufmgr, self->dec_in_port->use_buffer) != OMX_ErrorNone)
      return FALSE;
 #else
     if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
       return FALSE;
 #endif
-
+#ifndef TIZEN_FEATURE_OMX
     if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
       if (gst_omx_port_set_enabled (self->dec_out_port, TRUE) != OMX_ErrorNone)
         return FALSE;
@@ -2154,10 +2284,11 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
               5 * GST_SECOND) != OMX_ErrorNone)
         return FALSE;
     }
-
+#endif
     if (gst_omx_port_wait_enabled (self->dec_in_port,
             5 * GST_SECOND) != OMX_ErrorNone)
       return FALSE;
+
     if (gst_omx_port_mark_reconfigured (self->dec_in_port) != OMX_ErrorNone)
       return FALSE;
   } else {
@@ -2165,7 +2296,6 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
       GST_LOG_OBJECT (self, "Negotiation failed, will get output format later");
 
     if (!(klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
-#ifndef GST_TIZEN_MODIFICATION
       /* Disable output port */
       if (gst_omx_port_set_enabled (self->dec_out_port, FALSE) != OMX_ErrorNone)
         return FALSE;
@@ -2173,17 +2303,18 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
       if (gst_omx_port_wait_enabled (self->dec_out_port,
               1 * GST_SECOND) != OMX_ErrorNone)
         return FALSE;
-#endif
+
       if (gst_omx_component_set_state (self->dec,
               OMX_StateIdle) != OMX_ErrorNone)
         return FALSE;
 
       /* Need to allocate buffers to reach Idle state */
-#ifdef GST_TIZEN_MODIFICATION
-      if(gst_omx_port_tbm_allocate_dec_buffers(self->dec_in_port, self->hTBMBufMgr, 0) != OMX_ErrorNone)
+#ifdef TIZEN_FEATURE_OMX
+      if (gst_omx_port_tbm_allocate_dec_buffers (self->dec_in_port,
+          self->bufmgr, self->dec_in_port->use_buffer) != OMX_ErrorNone)
           return FALSE;
-      if(gst_omx_port_tbm_allocate_dec_buffers(self->dec_out_port, self->hTBMBufMgr,
-          self->dec_in_port->port_def.format.video.eCompressionFormat) != OMX_ErrorNone)
+      if (gst_omx_port_tbm_allocate_dec_buffers (self->dec_out_port,
+          self->bufmgr, self->dec_out_port->use_buffer) != OMX_ErrorNone)
           return FALSE;
 #else
       if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
@@ -2198,11 +2329,12 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
         return FALSE;
 
       /* Need to allocate buffers to reach Idle state */
-#ifdef GST_TIZEN_MODIFICATION
-      if(gst_omx_port_tbm_allocate_dec_buffers(self->dec_in_port, self->hTBMBufMgr, 0) != OMX_ErrorNone)
+#ifdef TIZEN_FEATURE_OMX
+      if (gst_omx_port_tbm_allocate_dec_buffers (self->dec_in_port,
+          self->bufmgr, self->dec_in_port->use_buffer) != OMX_ErrorNone)
           return FALSE;
-      if(gst_omx_port_tbm_allocate_dec_buffers(self->dec_out_port, self->hTBMBufMgr,
-          self->dec_in_port->port_def.format.video.eCompressionFormat) != OMX_ErrorNone)
+      if (gst_omx_port_tbm_allocate_dec_buffers (self->dec_out_port,
+          self->bufmgr, self->dec_out_port->use_buffer) != OMX_ErrorNone)
           return FALSE;
 #else
       if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
@@ -2422,9 +2554,8 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
         GST_VIDEO_DECODER_STREAM_LOCK (self);
         goto reconfigure_error;
       }
-#ifdef GST_TIZEN_MODIFICATION
-      err = gst_omx_port_tbm_allocate_dec_buffers(port, self->hTBMBufMgr,
-          self->dec_in_port->port_def.format.video.eCompressionFormat);
+#ifdef TIZEN_FEATURE_OMX
+      err = gst_omx_port_tbm_allocate_dec_buffers (port, self->bufmgr, port->use_buffer);
 #else
       err = gst_omx_port_allocate_buffers (port);
 #endif
@@ -2478,14 +2609,19 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
       buf->omx_buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
       buf->omx_buf->nFilledLen = gst_buffer_get_size (codec_data);;
 
-#ifdef GST_TIZEN_MODIFICATION
-      gst_buffer_extract (codec_data, 0,
-          buf->mm_vbuffer->data[0] + buf->omx_buf->nOffset,
-          buf->omx_buf->nFilledLen);
-#else
-      gst_buffer_extract (codec_data, 0,
-          buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
-          buf->omx_buf->nFilledLen);
+#ifdef TIZEN_FEATURE_OMX
+      if (port->use_buffer) {
+        gst_buffer_extract (codec_data, 0,
+            (OMX_U8 *) buf->mm_vbuffer->data[0] + buf->omx_buf->nOffset,
+            buf->omx_buf->nFilledLen);
+      } else {
+        gst_buffer_extract (codec_data, 0,
+            buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+            buf->omx_buf->nFilledLen);
+      }
+#ifdef CODEC_DEC_INTPUT_DUMP
+      decoder_input_dump (buf, port->use_buffer);
+#endif
 #endif
 
       if (GST_CLOCK_TIME_IS_VALID (timestamp))
@@ -2511,18 +2647,22 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
      * by the port */
     buf->omx_buf->nFilledLen =
         MIN (size - offset, buf->omx_buf->nAllocLen - buf->omx_buf->nOffset);
-    GST_DEBUG_OBJECT (self, "nFilledLen %d, %p", buf->omx_buf->nFilledLen, buf->omx_buf->pBuffer);
+    GST_DEBUG_OBJECT (self, "nFilledLen %lu, %p", buf->omx_buf->nFilledLen, buf->omx_buf->pBuffer);
 
-#ifdef GST_TIZEN_MODIFICATION
-     gst_buffer_extract (frame->input_buffer, offset,
-          buf->mm_vbuffer->data[0] + buf->omx_buf->nOffset,
+#ifdef TIZEN_FEATURE_OMX
+    if (port->use_buffer) {
+      gst_buffer_extract (frame->input_buffer, offset,
+          (OMX_U8 *) buf->mm_vbuffer->data[0] + buf->omx_buf->nOffset,
           buf->omx_buf->nFilledLen);
-#else
-    gst_buffer_extract (frame->input_buffer, offset,
-        buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
-        buf->omx_buf->nFilledLen);
+    } else {
+      gst_buffer_extract (frame->input_buffer, offset,
+          buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+          buf->omx_buf->nFilledLen);
+    }
+#ifdef CODEC_DEC_INTPUT_DUMP
+      decoder_input_dump (buf, port->use_buffer);
+#endif
 #endif
-
     if (timestamp != GST_CLOCK_TIME_NONE) {
       buf->omx_buf->nTimeStamp =
           gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND, GST_SECOND);
@@ -2780,3 +2920,72 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
 
   return TRUE;
 }
+
+#ifdef TIZEN_FEATURE_OMX
+static gboolean
+gst_omx_video_dec_acquire_request_flush_buffer (GstOMXVideoDec * self, GstBuffer ** flush_request_buffer)
+{
+  guint8 *dummy_data = NULL;
+  GstBuffer *buf = NULL;
+  MMVideoBuffer *mm_vbuffer = NULL;
+
+  GST_DEBUG_OBJECT (self, "flush buffer request");
+
+  if (self->out_port_pool) {
+    if (gst_buffer_pool_is_active(self->out_port_pool)) {
+      dummy_data = g_malloc0(128*128);
+      buf = gst_buffer_new_wrapped(dummy_data, 128*128);
+      mm_vbuffer = g_malloc(sizeof(MMVideoBuffer));
+
+      mm_vbuffer->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
+      mm_vbuffer->size[0] = 0;
+      mm_vbuffer->flush_request = TRUE;
+
+      gst_buffer_append_memory(buf,
+        gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, mm_vbuffer, sizeof(MMVideoBuffer), 0,
+          sizeof(MMVideoBuffer), mm_vbuffer, g_free));
+
+      *flush_request_buffer = buf;
+
+      GST_DEBUG_OBJECT (self, "flush buffer requested");
+      return TRUE;
+    } else {
+        GST_DEBUG_OBJECT (self, "the out port pool has not yet been activated");
+        return FALSE;
+    }
+  } else {
+    GST_DEBUG_OBJECT (self, "the output port has not yet been activated");
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_omx_video_dec_handle_event (GstVideoDecoder * decoder,
+    GstEvent * event)
+{
+  GstOMXVideoDec *self;
+
+  self = GST_OMX_VIDEO_DEC (decoder);
+
+  GST_DEBUG_OBJECT (self, "event: %s", GST_EVENT_TYPE_NAME (event));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH_START:
+    {
+      gst_omx_port_flush_start (self->dec_in_port, TRUE);
+      gst_omx_port_flush_start (self->dec_out_port, TRUE);
+      break;
+    }
+    case GST_EVENT_FLUSH_STOP:
+    {
+      gst_omx_port_flush_start (self->dec_in_port, FALSE);
+      gst_omx_port_flush_start (self->dec_out_port, FALSE);
+      break;
+    }
+    default:
+      break;
+  }
+
+  return GST_VIDEO_DECODER_CLASS (gst_omx_video_dec_parent_class)->sink_event (decoder, event);
+}
+#endif