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)
{
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)
_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);
_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 */
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,
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;
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 ()
{
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);
-}
#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
{
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;
}
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;
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;
}
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;
{
GstTizenMemory *tmem = (GstTizenMemory *) mem;
+ GST_DEBUG ("free surface from mem : %p", tmem->surface);
tbm_surface_internal_destroy (tmem->surface);
g_mutex_clear (&tmem->lock);
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,
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