Fixed bug when buffer released
authorSejun Park <sejun79.park@samsung.com>
Mon, 4 Jun 2018 08:09:12 +0000 (17:09 +0900)
committerSejun Park <sejun79.park@samsung.com>
Fri, 29 Jun 2018 06:51:06 +0000 (15:51 +0900)
Change-Id: Ieddde8491129195193cf0866cd5fd829cdf09fa8

gst-libs/gst/allocators/gsttizenbufferpool.c
gst-libs/gst/allocators/gsttizenbufferpool.h [changed mode: 0755->0644]
gst-libs/gst/allocators/gsttizenmemory.c
gst-libs/gst/allocators/gsttizenmemory.h
gst-libs/gst/video/video-converter.c
gst/videoconvert/gstvideoconvert.c
packaging/gst-plugins-base.spec [changed mode: 0755->0644]

index 48da5a2..2dffbee 100644 (file)
@@ -39,6 +39,11 @@ static void gst_tizen_buffer_pool_finalize (GObject * object);
 G_DEFINE_TYPE_WITH_CODE (GstTizenBufferPool, gst_tizen_buffer_pool,
     GST_TYPE_BUFFER_POOL, DEBUG_INIT);
 
+struct _GstTizenBufferPoolPrivate
+{
+  GstAllocator *allocator;
+};
+
 static const gchar **
 gst_tizen_buffer_pool_get_options (GstBufferPool * pool)
 {
@@ -56,8 +61,12 @@ gst_tizen_buffer_pool_set_config (GstBufferPool * pool,
   GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (pool);
   GstVideoInfo info;
   GstCaps *caps;
+  tbm_format format;
+  tbm_surface_h surface;
+  guint min_buffers, max_buffers;
+  int size;
 
-  if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
+  if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers, &max_buffers))
     goto wrong_config;
 
   if (caps == NULL)
@@ -72,6 +81,13 @@ gst_tizen_buffer_pool_set_config (GstBufferPool * pool,
 
   _tpool->info = info;
 
+  format = gst_video_format_to_tbm_format (GST_VIDEO_INFO_FORMAT (&info));
+
+  surface = tbm_surface_create (GST_VIDEO_INFO_WIDTH (&info), GST_VIDEO_INFO_HEIGHT (&info), format);
+  size = tbm_surface_internal_get_size (surface);
+
+  tbm_surface_destroy (surface);
+
   /* enable metadata based on config of the pool */
   _tpool->add_videometa =  gst_buffer_pool_config_has_option (config,
       GST_BUFFER_POOL_OPTION_VIDEO_META);
@@ -80,6 +96,10 @@ gst_tizen_buffer_pool_set_config (GstBufferPool * pool,
   _tpool->add_tizenmeta = gst_buffer_pool_config_has_option (config,
       GST_BUFFER_POOL_OPTION_TIZEN_META);
 
+  gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
+      max_buffers);
+
+  GST_DEBUG_OBJECT (_tpool, "min : %u, max : %u, size : %d", min_buffers, max_buffers, size);
   return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config);
 
   /* ERRORS */
@@ -106,11 +126,19 @@ unknown_format:
     GST_ELEMENT_ERROR (_tpool, RESOURCE, WRITE,
         ("Failed to create output image buffer of %dx%d pixels",
             info.width, info.height),
+
         ("Invalid input caps %" GST_PTR_FORMAT, caps));
     return FALSE;
   }
 }
 
+static void
+_destroy_tbm_surface (struct UserPtrData *data)
+{
+  tbm_surface_internal_destroy ((tbm_surface_h)data);
+  GST_DEBUG ("destroy surface %p", data);
+}
+
 /* This function handles GstBuffer creation */
 static GstFlowReturn
 gst_tizen_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
@@ -132,11 +160,11 @@ gst_tizen_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
   if (!(tizen_mem = gst_tizen_allocator_alloc ((GstAllocator *)_tpool->allocator, info)))
     goto mem_create_failed;
 
+  gst_buffer_append_memory (buf, tizen_mem);
+
   GST_DEBUG_OBJECT (pool, "mem allocated : %p, %dx%d n_plane : %d",
       buf, GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info));
 
-  gst_buffer_append_memory (buf, tizen_mem);
-
   if (_tpool->add_videometa) {
     GstVideoMeta *vmeta;
 
@@ -153,24 +181,129 @@ gst_tizen_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
     vmeta->unmap = gst_tizen_video_memory_unmap;
   }
 
+  gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf),
+      gst_tizen_buffer_data_quark, gst_tizen_memory_get_surface (tizen_mem), (GDestroyNotify) _destroy_tbm_surface);
+
   *buffer = buf;
+  g_ptr_array_add (_tpool->buffers, buf);
+  g_atomic_int_inc (&_tpool->current_buffer_index);
+  g_atomic_int_inc (&_tpool->outstandings);
 
   return GST_FLOW_OK;
 
   /* ERROR */
 no_buffer:
   {
-    GST_WARNING_OBJECT (pool, "can't create image");
+    GST_WARNING_OBJECT (pool, "Couldn't create buffer");
     return GST_FLOW_ERROR;
   }
 
 mem_create_failed:
   {
-    GST_WARNING_OBJECT (pool, "Could create GstTizen Memory");
+    GST_WARNING_OBJECT (pool, "Couldn't create GstTizen Memory");
     return GST_FLOW_ERROR;
   }
 }
 
+
+static GstFlowReturn
+gst_tizen_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
+    GstBufferPoolAcquireParams * params)
+{
+  GstFlowReturn ret;
+  GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (bpool);
+  GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
+  gint i, n;
+
+  ret = pclass->acquire_buffer (bpool, buffer, params);
+  if (ret != GST_FLOW_OK) {
+    GST_WARNING_OBJECT (_tpool, "Couldn't acquire buffer");
+    return ret;
+  }
+
+  n = _tpool->buffers->len;
+  for (i = 0; i < n; i++) {
+    GstBuffer *tmp = g_ptr_array_index (_tpool->buffers, i);
+
+    if (tmp == *buffer)
+      break;
+  }
+  g_assert (i != n);
+  g_atomic_int_set(&_tpool->current_buffer_index, i);
+
+  GST_BUFFER_TIMESTAMP (*buffer) = GST_CLOCK_TIME_NONE;
+  GST_BUFFER_OFFSET (*buffer) = GST_BUFFER_OFFSET_NONE;
+  GST_BUFFER_OFFSET_END (*buffer) = GST_BUFFER_OFFSET_NONE;
+
+  g_atomic_int_inc (&_tpool->outstandings);
+
+  g_mutex_lock (&_tpool->lock);
+  _tpool->empty = FALSE;
+  g_mutex_unlock (&_tpool->lock);
+
+  GST_DEBUG_OBJECT (_tpool, "acquire buffer %p, current index %d, num_live_buffer %d", *buffer, i, _tpool->outstandings);
+
+  return GST_FLOW_OK;
+}
+
+void
+gst_tizen_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
+{
+  GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (bpool);
+
+  GST_BUFFER_POOL_CLASS (gst_tizen_buffer_pool_parent_class)->release_buffer (bpool, buffer);
+
+  if (g_atomic_int_dec_and_test(&_tpool->outstandings)) {
+    g_mutex_lock (&_tpool->lock);
+    _tpool->empty = TRUE;
+    g_mutex_unlock (&_tpool->lock);
+  }
+  GST_DEBUG_OBJECT (_tpool, "release buffer %p, outstandings %d", buffer, _tpool->outstandings);
+}
+
+static void
+gst_tizen_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
+{
+  GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (bpool);
+  GST_DEBUG_OBJECT (_tpool, "free buffer %p, %d", buffer, _tpool->outstandings);
+
+  gst_mini_object_set_qdata (GST_MINI_OBJECT (buffer),
+      gst_tizen_buffer_data_quark, NULL, NULL);
+
+  GST_BUFFER_POOL_CLASS (gst_tizen_buffer_pool_parent_class)->free_buffer (bpool,
+      buffer);
+}
+
+static void
+gst_tizen_buffer_pool_dispose (GObject * object)
+{
+  GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (object);
+
+  if (_tpool->allocator) {
+    gst_object_unref (_tpool->allocator);
+    _tpool->allocator = NULL;
+  }
+
+  if (_tpool->buffers) {
+    g_ptr_array_unref (_tpool->buffers);
+    _tpool->buffers = NULL;
+  }
+
+  GST_DEBUG_OBJECT (_tpool, "dispose pool");
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_tizen_buffer_pool_finalize (GObject * object)
+{
+  GstTizenBufferPool *pool = GST_TIZEN_BUFFER_POOL_CAST (object);
+
+
+  g_mutex_clear (&pool->lock);
+
+  G_OBJECT_CLASS (gst_tizen_buffer_pool_parent_class)->finalize (object);
+}
+
 GstBufferPool *
 gst_tizen_buffer_pool_new ()
 {
@@ -183,29 +316,27 @@ gst_tizen_buffer_pool_class_init (GstTizenBufferPoolClass * klass)
   GObjectClass *gobject_class = (GObjectClass *) klass;
   GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
 
+  gst_tizen_buffer_data_quark = g_quark_from_static_string ("GstTizenBufferData");
+
+  gobject_class->dispose = gst_tizen_buffer_pool_dispose;
   gobject_class->finalize = gst_tizen_buffer_pool_finalize;
 
   gstbufferpool_class->get_options = gst_tizen_buffer_pool_get_options;
   gstbufferpool_class->set_config = gst_tizen_buffer_pool_set_config;
   gstbufferpool_class->alloc_buffer = gst_tizen_buffer_pool_alloc;
+  gstbufferpool_class->free_buffer = gst_tizen_buffer_pool_free_buffer;
+  gstbufferpool_class->acquire_buffer = gst_tizen_buffer_pool_acquire_buffer;
+  gstbufferpool_class->release_buffer = gst_tizen_buffer_pool_release_buffer;
 }
 
 static void
 gst_tizen_buffer_pool_init (GstTizenBufferPool * pool)
 {
+  g_mutex_init (&pool->lock);
+  pool->priv = gst_tizen_buffer_pool_get_instance_private (pool);
+  pool->buffers = g_ptr_array_new ();
   pool->allocator = gst_tizen_allocator_new ();
+  g_atomic_int_set(&pool->outstandings, 0);
   GST_LOG_OBJECT (pool, "Tizen buffer pool init %p", pool);
 }
 
-static void
-gst_tizen_buffer_pool_finalize (GObject * object)
-{
-  GstTizenBufferPool *pool = GST_TIZEN_BUFFER_POOL_CAST (object);
-
-  if (pool->allocator)
-    gst_object_unref (pool->allocator);
-
-  GST_LOG_OBJECT (pool, "finalize Tizen buffer pool %p", pool);
-
-  G_OBJECT_CLASS (gst_tizen_buffer_pool_parent_class)->finalize (object);
-}
old mode 100755 (executable)
new mode 100644 (file)
index 5be95b0..709a7df
@@ -40,6 +40,7 @@ G_BEGIN_DECLS
 
 typedef struct _GstTizenBufferPool GstTizenBufferPool;
 typedef struct _GstTizenBufferPoolClass GstTizenBufferPoolClass;
+typedef struct _GstTizenBufferPoolPrivate GstTizenBufferPoolPrivate;
 
 /* buffer pool functions */
 #define GST_TYPE_TIZEN_BUFFER_POOL      (gst_tizen_buffer_pool_get_type())
@@ -57,7 +58,14 @@ struct _GstTizenBufferPool
   gboolean      add_videometa;
   gboolean      add_tizenmeta;
 
-  gint current_buffer_index;
+  GMutex       lock;
+
+  GPtrArray    *buffers;
+  gint         current_buffer_index;
+  gint         outstandings;
+  gboolean     empty;
+
+  GstTizenBufferPoolPrivate *priv;
 };
 
 struct _GstTizenBufferPoolClass
index e5ca30a..b3f5442 100644 (file)
@@ -35,7 +35,9 @@ GST_DEBUG_CATEGORY_STATIC (gst_tizenmemory_debug);
 
 #define parent_class gst_tizen_allocator_parent_class
 G_DEFINE_TYPE_WITH_CODE (GstTizenAllocator, gst_tizen_allocator, GST_TYPE_ALLOCATOR,
-                         G_ADD_PRIVATE (GstTizenAllocator))
+    G_ADD_PRIVATE (GstTizenAllocator);
+    GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "tizenmemory", 0,
+        "GstTizenMemory and GstTizenAllocator"));
 
 typedef struct
 {
@@ -44,17 +46,16 @@ typedef struct
   GstVideoFormat nformat;    /* Gst native video format */
 } GstTizenBufferFormats;
 
-static tbm_format gst_video_format_to_tbm_format (GstVideoFormat format);
 static void cached_tizen_disposed_cb (GstTizenAllocator * allocator, GstMiniObject *obj);
 
-static const GstTizenBufferFormats yuv_formats[] = {
+GstTizenBufferFormats yuv_formats[] = {
     {TBM_FORMAT_YUV420, GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_S420},
     {TBM_FORMAT_NV21, GST_VIDEO_FORMAT_NV21, GST_VIDEO_FORMAT_SN21},
     {TBM_FORMAT_NV12, GST_VIDEO_FORMAT_NV12, GST_VIDEO_FORMAT_SN12},
     {TBM_FORMAT_BGRA8888, GST_VIDEO_FORMAT_BGRA, GST_VIDEO_FORMAT_SR32}
 };
 
-static tbm_format
+tbm_format
 gst_video_format_to_tbm_format (GstVideoFormat format)
 {
   gint i;
@@ -67,7 +68,7 @@ gst_video_format_to_tbm_format (GstVideoFormat format)
 }
 
 static GstTizenMemory *
-_tizen_video_mem_new (GstAllocator * allocator, GstMemory * parent, GstVideoInfo * vinfo)
+_tizen_video_mem_new (GstAllocator * allocator, GstMemory * parent, GstVideoInfo * vinfo, tbm_surface_h surface)
 {
   gint width, height;
   GstTizenMemory *tmem;
@@ -77,15 +78,18 @@ _tizen_video_mem_new (GstAllocator * allocator, GstMemory * parent, GstVideoInfo
 
   tmem = g_slice_new0 (GstTizenMemory);
 
-  width = GST_VIDEO_INFO_WIDTH (vinfo);
-  height = GST_VIDEO_INFO_HEIGHT (vinfo);
-
   /* Creates the tbm_surface with buffer objects. */
-  format = gst_video_format_to_tbm_format (GST_VIDEO_INFO_FORMAT (vinfo));
-  tmem->surface = tbm_surface_internal_create_with_flags (width, height, format, TBM_BO_DEFAULT);
+  if (surface) {
+    tmem->surface = surface;
+  } else {
+    width = GST_VIDEO_INFO_WIDTH (vinfo);
+    height = GST_VIDEO_INFO_HEIGHT (vinfo);
+    format = gst_video_format_to_tbm_format (GST_VIDEO_INFO_FORMAT (vinfo));
+    tmem->surface = tbm_surface_internal_create_with_flags (width, height, format, TBM_BO_NONCACHABLE);
+  }
 
-  if (!tmem->surface) {
-    GST_ERROR ("Failed to create tbm surface w :%d, h : %d, format : %x", width, height, format);
+  if (!tbm_surface_internal_is_valid (tmem->surface)) {
+    GST_ERROR ("Invalid tbm surface");
     goto failed;
   }
 
@@ -94,7 +98,6 @@ _tizen_video_mem_new (GstAllocator * allocator, GstMemory * parent, GstVideoInfo
   for (i = 0; i < sinfo.num_planes; i++) {
     GST_VIDEO_INFO_PLANE_STRIDE (vinfo, i) = sinfo.planes[i].stride;
     GST_VIDEO_INFO_PLANE_OFFSET (vinfo, i) = sinfo.planes[i].offset;
-
   }
   GST_VIDEO_INFO_SIZE (vinfo) = sinfo.size;
 
@@ -123,6 +126,7 @@ gst_tizen_mem_free (GstAllocator * allocator, GstMemory * mem)
 {
   GstTizenMemory *tmem = (GstTizenMemory *) mem;
 
+  GST_DEBUG ("free surface from mem : %p", tmem->surface);
   tbm_surface_internal_destroy (tmem->surface);
 
   g_mutex_clear (&tmem->lock);
@@ -245,8 +249,6 @@ gst_tizen_allocator_new (void)
   static volatile gsize _init = 0;
 
   if (g_once_init_enter (&_init)) {
-    GST_DEBUG_CATEGORY_INIT (gst_tizenmemory_debug, "tizenmemory", 0,
-        "GstTizenMemory and GstTizenAllocator");
 
     _tizen_allocator = g_object_new (GST_TYPE_TIZEN_ALLOCATOR, NULL);
         gst_allocator_register (GST_TIZEN_ALLOCATOR_NAME,
@@ -259,7 +261,13 @@ gst_tizen_allocator_new (void)
 GstMemory *
 gst_tizen_allocator_alloc (GstAllocator * allocator, GstVideoInfo * vinfo)
 {
-  return (GstMemory *)_tizen_video_mem_new (_tizen_allocator, NULL, vinfo);
+  return (GstMemory *)_tizen_video_mem_new (_tizen_allocator, NULL, vinfo, NULL);
+}
+
+GstMemory *
+gst_tizen_allocator_alloc_surface (GstAllocator * allocator, GstVideoInfo * vinfo, tbm_surface_h surface)
+{
+  return (GstMemory *)_tizen_video_mem_new (_tizen_allocator, NULL, vinfo, surface);
 }
 
 gboolean
index 0c0b701..c15b326 100644 (file)
@@ -91,6 +91,8 @@ GstAllocator *  gst_tizen_allocator_new    (void);
 
 GstMemory *     gst_tizen_allocator_alloc  (GstAllocator * allocator, GstVideoInfo * vinfo);
 
+GstMemory *     gst_tizen_allocator_alloc_surface (GstAllocator * allocator, GstVideoInfo * vinfo, tbm_surface_h surface);
+
 gboolean        gst_is_tizen_memory        (GstMemory *mem);
 
 gint            gst_tizen_memory_get_num_bos (GstMemory *mem);
@@ -106,6 +108,8 @@ gboolean        gst_tizen_video_memory_map (GstVideoMeta * meta, guint plane, Gs
 
 gboolean        gst_tizen_video_memory_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info);
 
+tbm_format gst_video_format_to_tbm_format (GstVideoFormat format);
+
 G_END_DECLS
 
 #endif /* _GST_TIZEN_MEMORY_H_ */
index d016b59..eee8079 100644 (file)
@@ -5804,8 +5804,8 @@ convert_I420_SN12 (GstVideoConverter * convert, const GstVideoFrame * src,
   gint height = convert->in_height;
 
   mY = mUV = Y = U = V = NULL;
-  mY = FRAME_GET_PLANE_LINE (dest, 0, 0);
-  mUV = FRAME_GET_PLANE_LINE (dest, 1, 0);
+  mY = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
+  mUV = GST_VIDEO_FRAME_PLANE_DATA (dest, 1);
 
   for (i = 0; i < GST_ROUND_DOWN_2 (height); i += 2) {
     GET_LINE_OFFSETS (interlaced, i, l1, l2);
index 9788fb9..18fea35 100644 (file)
@@ -514,16 +514,17 @@ gst_video_convert_finalize (GObject * obj)
 {
   GstVideoConvert *space = GST_VIDEO_CONVERT (obj);
 
-  if (space->convert) {
-    gst_video_converter_free (space->convert);
-  }
-#ifdef USE_TBM_BUFFER
+#ifdef USE_TBM
   if (space->pool) {
      gst_buffer_pool_set_active (space->pool, FALSE);
      gst_object_unref (space->pool);
      space->pool = NULL;
   }
 #endif
+
+  if (space->convert) {
+    gst_video_converter_free (space->convert);
+  }
   G_OBJECT_CLASS (parent_class)->finalize (obj);
 }
 
@@ -619,7 +620,7 @@ gst_video_convert_class_init (GstVideoConvertClass * klass)
 static void
 gst_video_convert_init (GstVideoConvert * space)
 {
-#ifdef USE_TBM_BUFFER
+#ifdef USE_TBM
   space->pool = NULL;
 #endif
   space->dither = DEFAULT_PROP_DITHER;
old mode 100755 (executable)
new mode 100644 (file)
index 72b3ec3..b2b83b1
@@ -5,7 +5,7 @@
 
 Name:           gst-plugins-base
 Version:        1.12.2
-Release:        3
+Release:        4
 License:        LGPL-2.0+
 Summary:        GStreamer Streaming-Media Framework Plug-Ins
 Url:            http://gstreamer.freedesktop.org/