[v4l2videodecoder] Support TBM for output buffer 04/248104/13 accepted/tizen/unified/20201228.130117 submit/tizen/20201224.112819
authorJeongmo Yang <jm80.yang@samsung.com>
Fri, 20 Nov 2020 12:10:23 +0000 (21:10 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Fri, 18 Dec 2020 08:33:30 +0000 (17:33 +0900)
[Version] 1.16.2-15
[Issue Type] Update

Change-Id: I96aed003f684a4f49ca1806dabdaf09b02cf042d
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
configure.ac
packaging/gst-plugins-good.spec
sys/v4l2/Makefile.am
sys/v4l2/gstv4l2.c
sys/v4l2/gstv4l2allocator.c
sys/v4l2/gstv4l2allocator.h
sys/v4l2/gstv4l2bufferpool.c
sys/v4l2/gstv4l2bufferpool.h
sys/v4l2/gstv4l2object.c
sys/v4l2/gstv4l2videodec.c

index 17c90f0..94aa6ba 100644 (file)
@@ -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)
index 96c5e1a..b2c52b9 100644 (file)
@@ -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\
index e4099bc..3d8f503 100644 (file)
@@ -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 = \
index e3e54d1..8a9ea97 100644 (file)
@@ -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);
index 05bde3d..5f6f554 100644 (file)
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <unistd.h>
+#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+#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;
index eb51524..7e959f0 100644 (file)
 #include "ext/videodev2.h"
 #include <gst/gst.h>
 #include <gst/gstatomicqueue.h>
+#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+#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 {
index 49f222b..6a3f5ea 100644 (file)
@@ -45,6 +45,9 @@
 #include "gstv4l2object.h"
 #include "gst/gst-i18n-plugin.h"
 #include <gst/glib-compat-private.h>
+#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
+#include <gst/allocators/gsttizenmemory.h>
+#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;
index bf0625d..62703ab 100644 (file)
@@ -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;
index d04cc3d..9db4ae6 100644 (file)
@@ -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);
index 0ce881c..1086958 100644 (file)
@@ -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))