From a9ea40efb522a2f013d853e08dbaf703610c8027 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Fri, 20 Nov 2020 21:10:23 +0900 Subject: [PATCH] [v4l2videodecoder] Support TBM for output buffer [Version] 1.16.2-15 [Issue Type] Update Change-Id: I96aed003f684a4f49ca1806dabdaf09b02cf042d Signed-off-by: Jeongmo Yang --- configure.ac | 3 + packaging/gst-plugins-good.spec | 6 +- sys/v4l2/Makefile.am | 2 + sys/v4l2/gstv4l2.c | 10 +++ sys/v4l2/gstv4l2allocator.c | 77 ++++++++++++++++++++- sys/v4l2/gstv4l2allocator.h | 13 +++- sys/v4l2/gstv4l2bufferpool.c | 145 +++++++++++++++++++++++++++++++++++++++- sys/v4l2/gstv4l2bufferpool.h | 6 ++ sys/v4l2/gstv4l2object.c | 49 ++++++++++++++ sys/v4l2/gstv4l2videodec.c | 40 +++++++++++ 10 files changed, 345 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 17c90f0..94aa6ba 100644 --- a/configure.ac +++ b/configure.ac @@ -1064,6 +1064,9 @@ AG_GST_CHECK_FEATURE(TWOLAME, [twolame], twolame, [ AC_SUBST(TWOLAME_LIBS) ]) +PKG_CHECK_MODULES(TBM, libtbm) +AC_SUBST(TBM_CFLAGS) +AC_SUBST(TBM_LIBS) dnl *** vpx *** translit(dnm, m, l) AM_CONDITIONAL(USE_VPX, vpx) diff --git a/packaging/gst-plugins-good.spec b/packaging/gst-plugins-good.spec index 96c5e1a..b2c52b9 100644 --- a/packaging/gst-plugins-good.spec +++ b/packaging/gst-plugins-good.spec @@ -3,7 +3,7 @@ Name: gst-plugins-good Version: 1.16.2 -Release: 14 +Release: 15 License: LGPL-2.1+ Summary: GStreamer Streaming-Media Framework Plug-Ins Url: http://gstreamer.freedesktop.org/ @@ -41,6 +41,7 @@ BuildRequires: pkgconfig(libv4l2) %endif BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(libtbm) Requires: gst-plugins-base >= 1.0.0 Requires: gstreamer >= 1.0.5 @@ -90,6 +91,7 @@ export CFLAGS+=" \ -DTIZEN_FEATURE_AVIDEMUX_MODIFICATION\ -DTIZEN_FEATURE_USE_LIBV4L2\ -DTIZEN_FEATURE_V4L2_ADDITIONAL_CID_SUPPORT\ + -DTIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER\ -fstack-protector-strong\ -Wl,-z,relro\ -D_FORTIFY_SOURCE=2" @@ -100,7 +102,7 @@ export CFLAGS+=" \ %if "%{tizen_profile_name}" != "tv" --with-libv4l2 \ %endif - --disable-v4l2-probe\ + --enable-v4l2-probe\ --disable-gtk-doc\ --with-gtk=3.0\ --disable-monoscope\ diff --git a/sys/v4l2/Makefile.am b/sys/v4l2/Makefile.am index e4099bc..3d8f503 100644 --- a/sys/v4l2/Makefile.am +++ b/sys/v4l2/Makefile.am @@ -35,6 +35,7 @@ libgstvideo4linux2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \ $(GST_CFLAGS) \ $(X_CFLAGS) \ $(LIBV4L2_CFLAGS) \ + $(TBM_CFLAGS) \ $(GUDEV_CFLAGS) libgstvideo4linux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) @@ -45,6 +46,7 @@ libgstvideo4linux2_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ $(GST_LIBS) \ $(LIBV4L2_LIBS) \ $(GUDEV_LIBS) \ + $(TBM_LIBS) \ $(LIBRT) noinst_HEADERS = \ diff --git a/sys/v4l2/gstv4l2.c b/sys/v4l2/gstv4l2.c index e3e54d1..8a9ea97 100644 --- a/sys/v4l2/gstv4l2.c +++ b/sys/v4l2/gstv4l2.c @@ -99,6 +99,16 @@ gst_v4l2_probe_template_caps (const gchar * device, gint video_fd, GstStructure *alt_t = NULL; switch (format.pixelformat) { +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + case V4L2_PIX_FMT_YUV420: + alt_t = gst_structure_copy (template); + gst_structure_set (alt_t, "format", G_TYPE_STRING, "S420", NULL); + break; + case V4L2_PIX_FMT_NV12: + alt_t = gst_structure_copy (template); + gst_structure_set (alt_t, "format", G_TYPE_STRING, "SN12", NULL); + break; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ case V4L2_PIX_FMT_RGB32: alt_t = gst_structure_copy (template); gst_structure_set (alt_t, "format", G_TYPE_STRING, "ARGB", NULL); diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c index 05bde3d..5f6f554 100644 --- a/sys/v4l2/gstv4l2allocator.c +++ b/sys/v4l2/gstv4l2allocator.c @@ -38,6 +38,10 @@ #include #include #include +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER +#include +#include +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ #define GST_V4L2_MEMORY_TYPE "V4l2Memory" @@ -235,6 +239,13 @@ gst_v4l2_memory_group_free (GstV4l2MemoryGroup * group) if (mem) gst_memory_unref (mem); } +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (group->surface) { + GST_INFO ("unref surface[%p]", group->surface); + tbm_surface_destroy (group->surface); + group->surface = NULL; + } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ g_slice_free (GstV4l2MemoryGroup, group); } @@ -428,6 +439,13 @@ gst_v4l2_allocator_finalize (GObject * obj) GstV4l2Allocator *allocator = (GstV4l2Allocator *) obj; GST_LOG_OBJECT (obj, "called"); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (allocator->bufmgr) { + GST_INFO_OBJECT (obj, "deinit tbm bufmgr %p", allocator->bufmgr); + tbm_bufmgr_deinit (allocator->bufmgr); + allocator->bufmgr = NULL; + } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ gst_atomic_queue_unref (allocator->free_queue); gst_object_unref (allocator->obj->element); @@ -620,7 +638,20 @@ _cleanup_failed_alloc (GstV4l2Allocator * allocator, GstV4l2MemoryGroup * group) } } - +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER +static tbm_format __get_tbm_format (GstVideoFormat gst_format) +{ + switch (gst_format) { + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_SN12: + return TBM_FORMAT_NV12; + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_S420: + default: + return TBM_FORMAT_YUV420; + } +} +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ GstV4l2Allocator * gst_v4l2_allocator_new (GstObject * parent, GstV4l2Object * v4l2object) @@ -660,6 +691,32 @@ gst_v4l2_allocator_new (GstObject * parent, GstV4l2Object * v4l2object) GST_OBJECT_FLAG_SET (allocator, flags); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (!V4L2_TYPE_IS_OUTPUT (v4l2object->type) && + v4l2object->mode == GST_V4L2_IO_DMABUF) { + tbm_surface_h tmp_surface = NULL; + int width = GST_VIDEO_INFO_WIDTH (&v4l2object->info); + int height = GST_VIDEO_INFO_HEIGHT (&v4l2object->info); + + tmp_surface = tbm_surface_create (width, height, + __get_tbm_format (GST_VIDEO_INFO_FORMAT (&v4l2object->info))); + if (tmp_surface) { + tbm_surface_get_info (tmp_surface, &allocator->s_info); + GST_INFO_OBJECT (allocator, "[%dx%d] -> tbm surface info[%dx%d]", + width, height, allocator->s_info.width, allocator->s_info.height); + tbm_surface_destroy (tmp_surface); + } else { + GST_ERROR_OBJECT (allocator, "[%dx%d] surface failed", width, height); + } + + allocator->bufmgr = tbm_bufmgr_init (-1); + if (!allocator->bufmgr) { + GST_ERROR_OBJECT (allocator, "tbm bufmgr failed"); + gst_object_unref (allocator); + return NULL; + } + } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ return allocator; } @@ -883,6 +940,9 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, GstV4l2Object *obj = allocator->obj; GstV4l2MemoryGroup *group; gint i; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + tbm_bo bos[VIDEO_MAX_PLANES] = {NULL, }; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ g_return_val_if_fail (allocator->memory == V4L2_MEMORY_MMAP, NULL); @@ -913,6 +973,11 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, NULL, group->planes[i].length, 0, group->planes[i].data_offset, group->planes[i].length - group->planes[i].data_offset, i, NULL, expbuf.fd, group); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + bos[i] = tbm_bo_import_fd (allocator->bufmgr, expbuf.fd); + GST_INFO_OBJECT (allocator, "obj[%p,i:%d]: fd[%d] -> bo[%p]", + obj, expbuf.index, expbuf.fd, bos[i]); +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ } else { /* Take back the allocator reference */ gst_object_ref (allocator); @@ -934,6 +999,16 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, group->mem[i] = dma_mem; } +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (!group->surface) { + group->surface = tbm_surface_internal_create_with_bos (&allocator->s_info, bos, group->n_mem); + GST_INFO_OBJECT (allocator, "new surface[%p] in memory group[%p]", group->surface, group); + } + /* release bos - they will be kept in surface. */ + for (i = 0 ; i < VIDEO_MAX_PLANES && bos[i] ; i++) + tbm_bo_unref (bos[i]); +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ + gst_v4l2_allocator_reset_size (allocator, group); return group; diff --git a/sys/v4l2/gstv4l2allocator.h b/sys/v4l2/gstv4l2allocator.h index eb51524..7e959f0 100644 --- a/sys/v4l2/gstv4l2allocator.h +++ b/sys/v4l2/gstv4l2allocator.h @@ -26,6 +26,10 @@ #include "ext/videodev2.h" #include #include +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER +#include +#include +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ G_BEGIN_DECLS @@ -90,6 +94,9 @@ struct _GstV4l2MemoryGroup gint mems_allocated; struct v4l2_buffer buffer; struct v4l2_plane planes[VIDEO_MAX_PLANES]; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + tbm_surface_h surface; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ }; struct _GstV4l2Allocator @@ -104,7 +111,11 @@ struct _GstV4l2Allocator GstV4l2MemoryGroup * groups[VIDEO_MAX_FRAME]; GstAtomicQueue *free_queue; GstAtomicQueue *pending_queue; - +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + tbm_bufmgr bufmgr; + tbm_surface_info_s s_info; + gint live_buffer_count; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ }; struct _GstV4l2AllocatorClass { diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c index 49f222b..6a3f5ea 100644 --- a/sys/v4l2/gstv4l2bufferpool.c +++ b/sys/v4l2/gstv4l2bufferpool.c @@ -45,6 +45,9 @@ #include "gstv4l2object.h" #include "gst/gst-i18n-plugin.h" #include +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER +#include +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ GST_DEBUG_CATEGORY_STATIC (v4l2bufferpool_debug); GST_DEBUG_CATEGORY_STATIC (CAT_PERFORMANCE); @@ -52,7 +55,6 @@ GST_DEBUG_CATEGORY_STATIC (CAT_PERFORMANCE); #define GST_V4L2_IMPORT_QUARK gst_v4l2_buffer_pool_import_quark () - /* * GstV4l2BufferPool: */ @@ -68,6 +70,72 @@ enum _GstV4l2BufferPoolAcquireFlags static void gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER +typedef struct _GstV4l2TizenBuffer GstV4l2TizenBuffer; +struct _GstV4l2TizenBuffer { + int index; + GstBuffer *gst_buffer; + GstBuffer *v4l2_buffer; + GstV4l2BufferPool *v4l2_pool; +}; + +static void gst_v4l2_tizen_buffer_finalize (GstV4l2TizenBuffer *tizen_buffer) +{ + GstV4l2BufferPool *pool = NULL; + + if (!tizen_buffer) { + GST_ERROR ("NULL buffer"); + return; + } + + pool = tizen_buffer->v4l2_pool; + + gst_v4l2_buffer_pool_release_buffer (GST_BUFFER_POOL_CAST (pool), tizen_buffer->v4l2_buffer); + + g_mutex_lock (&pool->buffer_lock); + + pool->live_buffer_count--; + + GST_DEBUG_OBJECT (pool, "release buffer[%d][tizen:%p,v4l2:%p,gst:%p], live[%d]", + tizen_buffer->index, tizen_buffer, tizen_buffer->v4l2_buffer, + tizen_buffer->gst_buffer, pool->live_buffer_count); + + g_cond_signal (&pool->buffer_cond); + + g_mutex_unlock (&pool->buffer_lock); +} + +static GstV4l2TizenBuffer *gst_v4l2_tizen_buffer_new (GstBuffer *v4l2_buffer, int index, GstV4l2BufferPool *v4l2_pool) +{ + GstV4l2TizenBuffer *tizen_buffer = NULL; + GstMemory *memory = NULL; + + tizen_buffer = g_new0 (GstV4l2TizenBuffer, 1); + tizen_buffer->index = index; + tizen_buffer->v4l2_buffer = v4l2_buffer; + tizen_buffer->gst_buffer = gst_buffer_new (); + tizen_buffer->v4l2_pool = v4l2_pool; + + memory = gst_tizen_allocator_alloc_surface (v4l2_pool->tallocator, + &v4l2_pool->obj->info, v4l2_pool->vallocator->groups[index]->surface, (gpointer)tizen_buffer, + (GDestroyNotify)gst_v4l2_tizen_buffer_finalize); + + gst_buffer_append_memory (tizen_buffer->gst_buffer, memory); + gst_buffer_set_size (tizen_buffer->gst_buffer, v4l2_pool->vallocator->s_info.size); + + g_mutex_lock (&v4l2_pool->buffer_lock); + + v4l2_pool->live_buffer_count++; + + GST_DEBUG_OBJECT (v4l2_pool, "new buffer[tizen:%p,v4l2:%p,gst:%p], size[%d], live[%d]", + tizen_buffer, v4l2_buffer, tizen_buffer->gst_buffer, + v4l2_pool->vallocator->s_info.size, v4l2_pool->live_buffer_count); + + g_mutex_unlock (&v4l2_pool->buffer_lock); + + return tizen_buffer; +} +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ static gboolean gst_v4l2_is_buffer_valid (GstBuffer * buffer, GstV4l2MemoryGroup ** out_group) @@ -649,6 +717,7 @@ gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool) case GST_V4L2_IO_USERPTR: case GST_V4L2_IO_DMABUF: case GST_V4L2_IO_DMABUF_IMPORT: +#ifndef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type)) { guint i; @@ -659,6 +728,7 @@ gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool) for (i = 0; i < pool->num_allocated; i++) gst_v4l2_buffer_pool_resurrect_buffer (pool); } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ if (obj->ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0) goto streamon_failed; @@ -688,10 +758,38 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool) GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class); GstV4l2Object *obj = pool->obj; gint i; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + gint64 end_time = 0; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ if (!pool->streaming) return; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (!V4L2_TYPE_IS_OUTPUT(pool->obj->type)) { + g_mutex_lock (&pool->buffer_lock); + + GST_INFO_OBJECT (pool, "live buffer[%d]", pool->live_buffer_count); + + if (pool->live_buffer_count > 0) { + end_time = g_get_monotonic_time () + G_TIME_SPAN_SECOND; + + do { + GST_WARNING_OBJECT (pool, "wait for live buffer[%d]", pool->live_buffer_count); + + if (!g_cond_wait_until (&pool->buffer_cond, &pool->buffer_lock, end_time)) { + GST_ERROR_OBJECT (pool, "failed to wait live buffer[%d]", pool->live_buffer_count); + break; + } + + GST_WARNING_OBJECT (pool, "signal received, check again : live count[%d]", + pool->live_buffer_count); + } while (pool->live_buffer_count > 0); + } + + g_mutex_unlock (&pool->buffer_lock); + } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ switch (obj->mode) { case GST_V4L2_IO_MMAP: case GST_V4L2_IO_USERPTR: @@ -1215,6 +1313,9 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer, GstVideoMeta *vmeta; gsize size; gint i; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + GstV4l2TizenBuffer *tizen_buffer = NULL; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ if ((res = gst_v4l2_buffer_pool_poll (pool, wait)) < GST_FLOW_OK) goto poll_failed; @@ -1347,6 +1448,16 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer, GST_BUFFER_OFFSET (outbuf) = group->buffer.sequence; GST_BUFFER_OFFSET_END (outbuf) = group->buffer.sequence + 1; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (group->surface) { + tizen_buffer = gst_v4l2_tizen_buffer_new (outbuf, group->buffer.index, pool); + if (!tizen_buffer) { + GST_ERROR_OBJECT (pool, "tizen buffer failed for index[%d]", group->buffer.index); + goto no_buffer; + } + outbuf = tizen_buffer->gst_buffer; + } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ done: *buffer = outbuf; @@ -1585,6 +1696,14 @@ gst_v4l2_buffer_pool_dispose (GObject * object) gst_object_unref (pool->allocator); pool->allocator = NULL; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + g_cond_clear (&pool->buffer_cond); + g_mutex_clear (&pool->buffer_lock); + + if (pool->tallocator) + gst_object_unref (pool->tallocator); + pool->tallocator = NULL; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ if (pool->other_pool) gst_object_unref (pool->other_pool); pool->other_pool = NULL; @@ -1690,6 +1809,14 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps) pool->obj = obj; pool->can_poll_device = TRUE; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + pool->tallocator = gst_tizen_allocator_new (); + if (pool->tallocator == NULL) + goto allocator_failed; + + g_mutex_init (&pool->buffer_lock); + g_cond_init (&pool->buffer_cond); +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ pool->vallocator = gst_v4l2_allocator_new (GST_OBJECT (pool), obj); if (pool->vallocator == NULL) goto allocator_failed; @@ -1712,6 +1839,12 @@ dup_failed: } allocator_failed: { +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (pool->tallocator) { + gst_object_unref (pool->tallocator); + pool->tallocator = NULL; + } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ GST_ERROR_OBJECT (pool, "Failed to create V4L2 allocator"); gst_object_unref (pool); return NULL; @@ -1881,11 +2014,19 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf) if (GST_V4L2_IS_M2M (obj->device_caps)) goto eos; } - +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (pool->obj->mode == GST_V4L2_IO_DMABUF) { + gst_buffer_unref (*buf); + *buf = tmp; + } else { +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ ret = gst_v4l2_buffer_pool_copy_buffer (pool, *buf, tmp); /* an queue the buffer again after the copy */ gst_v4l2_buffer_pool_release_buffer (bpool, tmp); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ if (ret != GST_FLOW_OK) goto copy_failed; diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h index bf0625d..62703ab 100644 --- a/sys/v4l2/gstv4l2bufferpool.h +++ b/sys/v4l2/gstv4l2bufferpool.h @@ -68,6 +68,12 @@ struct _GstV4l2BufferPool GstV4l2Allocator *vallocator; GstAllocator *allocator; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + GstAllocator *tallocator; + gint live_buffer_count; + GMutex buffer_lock; + GCond buffer_cond; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ GstAllocationParams params; GstBufferPool *other_pool; guint size; diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index d04cc3d..9db4ae6 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -829,7 +829,16 @@ gst_v4l2_get_driver_min_buffers (GstV4l2Object * v4l2object) if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) == 0) { GST_DEBUG_OBJECT (v4l2object->dbg_obj, "driver requires a minimum of %d buffers", control.value); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER +#define DEFAULT_DECODER_OUTPUT_BUFFER_COUNT 5 + if (!V4L2_TYPE_IS_OUTPUT (v4l2object->type) && control.value == 1) { + v4l2object->min_buffers = DEFAULT_DECODER_OUTPUT_BUFFER_COUNT; + GST_WARNING_OBJECT (v4l2object->dbg_obj, "but SET MIN BUFFER COUNT[%d] and it will be [%d] later", + v4l2object->min_buffers, v4l2object->min_buffers + 1); + } +#else /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ v4l2object->min_buffers = control.value; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ } else { v4l2object->min_buffers = 0; } @@ -1627,6 +1636,16 @@ gst_v4l2_object_get_caps_helper (GstV4L2FormatFlags flags) } switch (gst_v4l2_formats[i].format) { +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + case V4L2_PIX_FMT_YUV420: + alt_s = gst_structure_copy (structure); + gst_structure_set (alt_s, "format", G_TYPE_STRING, "S420", NULL); + break; + case V4L2_PIX_FMT_NV12: + alt_s = gst_structure_copy (structure); + gst_structure_set (alt_s, "format", G_TYPE_STRING, "SN12", NULL); + break; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ case V4L2_PIX_FMT_RGB32: alt_s = gst_structure_copy (structure); gst_structure_set (alt_s, "format", G_TYPE_STRING, "ARGB", NULL); @@ -1716,6 +1735,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, if (g_str_equal (mimetype, "video/x-raw")) { switch (GST_VIDEO_INFO_FORMAT (info)) { case GST_VIDEO_FORMAT_I420: +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + case GST_VIDEO_FORMAT_S420: +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ fourcc = V4L2_PIX_FMT_YUV420; fourcc_nc = V4L2_PIX_FMT_YUV420M; break; @@ -1735,6 +1757,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, fourcc = V4L2_PIX_FMT_YUV422P; break; case GST_VIDEO_FORMAT_NV12: +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + case GST_VIDEO_FORMAT_SN12: +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ fourcc = V4L2_PIX_FMT_NV12; fourcc_nc = V4L2_PIX_FMT_NV12M; break; @@ -4259,6 +4284,25 @@ gst_v4l2_object_probe_caps (GstV4l2Object * v4l2object, GstCaps * filter) if (tmp) gst_caps_append (ret, tmp); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (format->pixelformat == V4L2_PIX_FMT_NV12 || + format->pixelformat == V4L2_PIX_FMT_YUV420) { + GstStructure *alt_s = gst_structure_copy (template); + + if (format->pixelformat == V4L2_PIX_FMT_NV12) + gst_structure_set (alt_s, "format", G_TYPE_STRING, "SN12", NULL); + else + gst_structure_set (alt_s, "format", G_TYPE_STRING, "S420", NULL); + + tmp = gst_v4l2_object_probe_caps_for_format (v4l2object, + format->pixelformat, alt_s); + + if (tmp) + gst_caps_append (ret, tmp); + + gst_structure_free (alt_s); + } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ gst_structure_free (template); } @@ -4306,7 +4350,12 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query) GstAllocator *allocator = NULL; GstAllocationParams params = { 0 }; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + GST_INFO_OBJECT (obj->dbg_obj, "decide allocation - %s", + V4L2_TYPE_IS_OUTPUT (obj->type) ? "output" : "capture"); +#else /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ GST_DEBUG_OBJECT (obj->dbg_obj, "decide allocation"); +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ g_return_val_if_fail (obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, FALSE); diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c index 0ce881c..1086958 100644 --- a/sys/v4l2/gstv4l2videodec.c +++ b/sys/v4l2/gstv4l2videodec.c @@ -59,6 +59,23 @@ G_DEFINE_ABSTRACT_TYPE (GstV4l2VideoDec, gst_v4l2_video_dec, static GstFlowReturn gst_v4l2_video_dec_finish (GstVideoDecoder * decoder); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER +static void gst_v4l2_video_dec_flush_buffer_event (GstVideoDecoder * decoder) +{ + gboolean ret = FALSE; + + if (!decoder) { + GST_ERROR("no decoder"); + return; + } + + ret = gst_pad_push_event (decoder->srcpad, + gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM | GST_EVENT_TYPE_SERIALIZED, + gst_structure_new_empty("tizen/flush-buffer"))); + + GST_WARNING_OBJECT(decoder, "event push ret[%d] for flush-buffer", ret); +} +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ static void gst_v4l2_video_dec_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -198,6 +215,9 @@ gst_v4l2_video_dec_stop (GstVideoDecoder * decoder) /* Should have been flushed already */ g_assert (g_atomic_int_get (&self->active) == FALSE); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + gst_v4l2_video_dec_flush_buffer_event (decoder); +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ gst_v4l2_object_stop (self->v4l2output); gst_v4l2_object_stop (self->v4l2capture); @@ -311,6 +331,9 @@ gst_v4l2_video_dec_flush (GstVideoDecoder * decoder) if (self->v4l2output->pool) gst_v4l2_buffer_pool_flush (self->v4l2output->pool); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + gst_v4l2_video_dec_flush_buffer_event (decoder); +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ /* gst_v4l2_buffer_pool_flush() calls streamon the capture pool and must be * called after gst_v4l2_object_unlock_stop() stopped flushing the buffer * pool. */ @@ -570,6 +593,10 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder, gboolean processed = FALSE; GstBuffer *tmp; GstTaskState task_state; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + GstStructure *structure = NULL; + const gchar *caps_format = NULL; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number); @@ -669,6 +696,19 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder, caps = gst_caps_fixate (caps); GST_DEBUG_OBJECT (self, "Chosen decoded caps: %" GST_PTR_FORMAT, caps); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + structure = gst_caps_get_structure (caps, 0); + caps_format = gst_structure_get_string (structure, "format"); + + if (!strcmp (caps_format, "I420")) { + GST_INFO_OBJECT (self, "I420 -> S420"); + gst_caps_set_simple (caps, "format", G_TYPE_STRING, "S420", NULL); + } else if (!strcmp (caps_format, "NV12")) { + GST_INFO_OBJECT (self, "NV12 -> SN12"); + gst_caps_set_simple (caps, "format", G_TYPE_STRING, "SN12", NULL); + } + GST_INFO_OBJECT (self, "Updated decoded caps: %" GST_PTR_FORMAT, caps); +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ /* Try to set negotiated format, on success replace acquired format */ if (gst_v4l2_object_set_format (self->v4l2capture, caps, &error)) -- 2.7.4