Merge branch 'tizen' into tizen_gst_1.19.2
authorJeongmo Yang <jm80.yang@samsung.com>
Fri, 21 Jan 2022 07:24:28 +0000 (16:24 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Tue, 25 Jan 2022 02:01:37 +0000 (11:01 +0900)
Change-Id: I40281f0aebdf537983a93bfa4d7d78f42860ba68
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
24 files changed:
1  2 
config/exynos/gstomx.conf
config/exynos/meson.build
config/exynos64/gstomx.conf
config/exynos64/meson.build
config/odroid/gstomx.conf
config/odroid/meson.build
config/rpi/gstomx.conf
examples/egl/testegl.c
meson.build
meson_options.txt
omx/gstomx.c
omx/gstomx.h
omx/gstomxallocator.c
omx/gstomxallocator.h
omx/gstomxbufferpool.c
omx/gstomxbufferpool.h
omx/gstomxh264dec.c
omx/gstomxh264enc.c
omx/gstomxh264enc.h
omx/gstomxvideo.c
omx/gstomxvideodec.c
omx/gstomxvideoenc.c
omx/meson.build
packaging/gst-omx.spec

index 0000000,e83ec55..e83ec55
mode 000000,100755..100644
--- /dev/null
index 0000000,0000000..dc99c08
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1 @@@
++install_data (['gstomx.conf'], install_dir : omx_conf_dir)
index 0000000,7726c17..7726c17
mode 000000,100755..100644
--- /dev/null
index 0000000,0000000..dc99c08
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1 @@@
++install_data (['gstomx.conf'], install_dir : omx_conf_dir)
index 0000000,0106ef2..0106ef2
mode 000000,100755..100644
--- /dev/null
index 0000000,0000000..dc99c08
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1 @@@
++install_data (['gstomx.conf'], install_dir : omx_conf_dir)
diff --cc meson.build
@@@ -222,13 -212,10 +222,22 @@@ elif omx_target == 'tizonia
    cdata.set('TIZONIA_LIBDIR', tizil_dep.get_pkgconfig_variable('libdir'))
    tizil_includedir = tizil_dep.get_pkgconfig_variable('includedir')
    gst_omx_args += ['-I' + tizil_includedir + '/tizonia']
 +  omx_inc = []
++elif omx_target == 'exynos64'
++  cdata.set('USE_OMX_TARGET_EXYNOS64', 1)
++elif omx_target == 'exynos'
++  cdata.set('USE_OMX_TARGET_EXYNOS', 1)
  else
    error ('Unsupported omx target specified. Use the -Dtarget option')
  endif
  
 +message ('OMX target: ' + omx_target)
 +
++# Tizen options
++tbm_dep = dependency('libtbm', required : true)
++have_omx_vp9 = get_option('vp9')
++cdata.set ('HAVE_VP9', have_omx_vp9)
++
  extra_video_headers = ''
  # Check for optional OpenMAX extension headers
  
@@@ -1,7 -1,7 +1,7 @@@
  option('header_path', type : 'string', value : '',
      description : 'An extra include directory to find the OpenMax headers')
  option('target', type : 'combo',
--    choices : ['none', 'generic', 'rpi', 'bellagio', 'tizonia', 'zynqultrascaleplus'], value : 'none',
++    choices : ['none', 'generic', 'rpi', 'bellagio', 'tizonia', 'zynqultrascaleplus', 'exynos64', 'exynos'], value : 'none',
      description : 'The OMX platform to target')
  option('struct_packing', type : 'combo',
      choices : ['0', '1', '2', '4', '8'], value : '0',
@@@ -11,4 -11,3 +11,9 @@@
  option('examples', type : 'feature', value : 'auto', yield : true)
  option('tests', type : 'feature', value : 'auto', yield : true)
  option('tools', type : 'feature', value : 'auto', yield : true)
 +option('doc', type : 'feature', value : 'auto', yield : true)
++
++# Tizen options
++option('vp9', type : 'boolean', value : false,
++    description : 'VP9 decoder for exynos')
++
diff --cc omx/gstomx.c
Simple merge
diff --cc omx/gstomx.h
Simple merge
index a180669,0000000..f625d9b
mode 100644,000000..100644
--- /dev/null
@@@ -1,554 -1,0 +1,599 @@@
 +/*
 + * Copyright (C) 2019, Collabora Ltd.
 + *   Author: George Kiagiadakis <george.kiagiadakis@collabora.com>
 + *
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation
 + * version 2.1 of the License.
 + *
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with this library; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 + *
 + */
 +
 +#ifdef HAVE_CONFIG_H
 +#include "config.h"
 +#endif
 +
 +#include "gstomxallocator.h"
 +#include <gst/allocators/gstdmabuf.h>
 +
 +GST_DEBUG_CATEGORY_STATIC (gst_omx_allocator_debug_category);
 +#define GST_CAT_DEFAULT gst_omx_allocator_debug_category
 +
 +#define DEBUG_INIT \
 +  GST_DEBUG_CATEGORY_INIT (gst_omx_allocator_debug_category, "omxallocator", 0, \
 +      "debug category for gst-omx allocator class");
 +
 +G_DEFINE_TYPE_WITH_CODE (GstOMXAllocator, gst_omx_allocator, GST_TYPE_ALLOCATOR,
 +    DEBUG_INIT);
 +
 +enum
 +{
 +  SIG_OMXBUF_RELEASED,
 +  SIG_FOREIGN_MEM_RELEASED,
 +  LAST_SIGNAL
 +};
 +
 +static guint signals[LAST_SIGNAL] = { 0 };
 +
 +/* Custom allocator for memory associated with OpenMAX buffers
 + *
 + * The main purpose of this allocator is to track memory that is associated
 + * with OpenMAX buffers, so that we know when the buffers can be released
 + * back to OpenMAX.
 + *
 + * This allocator looks and behaves more like a buffer pool. It allocates
 + * the memory objects before starting and sets a miniobject dispose function
 + * on them, which allows them to return when their last ref count is dropped.
 + *
 + * The type of memory that this allocator manages is GstOMXMemory. However, it
 + * is possible to manage a different type of memory, in which case the
 + * GstOMXMemory object is used only internally. There are two supported cases:
 + * - Allocate memory from the dmabuf allocator
 + * - Take memory that was allocated externally and manage it here
 + *
 + * In both cases, this allocator will replace the miniobject dispose function
 + * of these memory objects, so if they were acquired from here, they will also
 + * return here on their last unref.
 + *
 + * The caller initially needs to configure how many memory objects will be
 + * managed here by calling configure(). After that it needs to call
 + * set_active(TRUE) and finally allocate() for each memory. Allocation is done
 + * like this to facilitate calling allocate() from the alloc() function of
 + * the buffer pool for each OMX buffer on the port.
 + *
 + * After the allocator has been activated and all buffers have been allocated,
 + * the acquire() method can be called to retrieve a memory object. acquire() can
 + * be given an OMX buffer index or pointer to locate and return the memory
 + * object that corresponds to this OMX buffer. If the buffer is already
 + * acquired, this will result in a GST_FLOW_ERROR.
 + *
 + * When the last reference count is dropped on a memory that was acquired from
 + * here, its dispose function will ref it again and allow it to be acquired
 + * again. In addition, the omxbuf-released signal is fired to let the caller
 + * know that it can return this OMX buffer to the port, as it is no longer
 + * used outside this allocator.
 + */
 +
 +/******************/
 +/** GstOMXMemory **/
 +/******************/
 +
 +#define GST_OMX_MEMORY_TYPE "openmax"
 +
 +GQuark
 +gst_omx_memory_quark (void)
 +{
 +  static GQuark quark = 0;
 +
 +  if (quark == 0)
 +    quark = g_quark_from_static_string ("GstOMXMemory");
 +
 +  return quark;
 +}
 +
 +static GstOMXMemory *
 +gst_omx_memory_new (GstOMXAllocator * allocator, GstOMXBuffer * omx_buf,
 +    GstMemoryFlags flags, GstMemory * parent, gssize offset, gssize size)
 +{
 +  GstOMXMemory *mem;
 +  gint align;
 +  gsize maxsize;
 +
 +  /* GStreamer uses a bitmask for the alignment while
 +   * OMX uses the alignment itself. So we have to convert
 +   * here */
 +  align = allocator->port->port_def.nBufferAlignment;
 +  if (align > 0)
 +    align -= 1;
 +  if (((align + 1) & align) != 0) {
 +    GST_WARNING ("Invalid alignment that is not a power of two: %u",
 +        (guint) allocator->port->port_def.nBufferAlignment);
 +    align = 0;
 +  }
 +
 +  maxsize = omx_buf->omx_buf->nAllocLen;
 +
 +  if (size == -1) {
 +    size = maxsize - offset;
 +  }
 +
 +  mem = g_slice_new0 (GstOMXMemory);
 +  gst_memory_init (GST_MEMORY_CAST (mem), flags, (GstAllocator *) allocator,
 +      parent, maxsize, align, offset, size);
 +
 +  mem->buf = omx_buf;
 +
 +  return mem;
 +}
 +
 +static gpointer
 +gst_omx_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
 +{
 +  GstOMXMemory *omem = (GstOMXMemory *) mem;
 +
++#ifdef TIZEN_FEATURE_OMX
++  int err;
++  gpointer data = NULL;
++  tbm_surface_info_s info;
++  GstTizenMemory *tmem = (GstTizenMemory *)omem->foreign_mem;
++
++  g_mutex_lock (&tmem->lock);
++  err = tbm_surface_map (tmem->surface, TBM_SURF_OPTION_WRITE|TBM_SURF_OPTION_READ, &info);
++  if (err == TBM_SURFACE_ERROR_NONE)
++    data = info.planes[0].ptr;
++  g_mutex_unlock (&tmem->lock);
++
++  return data;
++#else
 +  /* if we are using foreign_mem, the GstOMXMemory should never appear
 +   * anywhere outside this allocator, therefore it should never be mapped */
 +  g_return_val_if_fail (!omem->foreign_mem, NULL);
 +
 +  return omem->buf->omx_buf->pBuffer;
++#endif
 +}
 +
 +static void
 +gst_omx_memory_unmap (GstMemory * mem)
 +{
++#ifdef TIZEN_FEATURE_OMX
++  GstOMXMemory *omem = (GstOMXMemory *) mem;
++  GstTizenMemory *tmem = (GstTizenMemory *)omem->foreign_mem;
++
++  g_mutex_lock (&tmem->lock);
++  tbm_surface_unmap (tmem->surface);
++  g_mutex_unlock (&tmem->lock);
++#endif
 +}
 +
 +static GstMemory *
 +gst_omx_memory_share (GstMemory * mem, gssize offset, gssize size)
 +{
 +  GstOMXMemory *omem = (GstOMXMemory *) mem;
 +  GstOMXMemory *sub;
 +  GstMemory *parent;
 +
 +  /* find the real parent */
 +  if ((parent = mem->parent) == NULL)
 +    parent = mem;
 +
 +  if (size == -1)
 +    size = mem->size - offset;
 +
 +  /* the shared memory is always readonly */
 +  sub = gst_omx_memory_new ((GstOMXAllocator *) mem->allocator, omem->buf,
 +      GST_MINI_OBJECT_FLAGS (parent) | GST_MINI_OBJECT_FLAG_LOCK_READONLY,
 +      parent, offset, size);
 +
 +  return (GstMemory *) sub;
 +}
 +
 +GstOMXBuffer *
 +gst_omx_memory_get_omx_buf (GstMemory * mem)
 +{
 +  GstOMXMemory *omx_mem;
 +
 +  if (GST_IS_OMX_ALLOCATOR (mem->allocator))
 +    omx_mem = (GstOMXMemory *) mem;
 +  else
 +    omx_mem = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
 +        GST_OMX_MEMORY_QUARK);
 +
 +  if (!omx_mem)
 +    return NULL;
 +
 +  return omx_mem->buf;
 +}
 +
 +/*********************/
 +/** GstOMXAllocator **/
 +/*********************/
 +
 +static void
 +gst_omx_allocator_init (GstOMXAllocator * allocator)
 +{
 +  GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
 +
 +  alloc->mem_type = GST_OMX_MEMORY_TYPE;
 +
 +  alloc->mem_map = gst_omx_memory_map;
 +  alloc->mem_unmap = gst_omx_memory_unmap;
 +  alloc->mem_share = gst_omx_memory_share;
 +  /* default copy & is_span */
 +
 +  GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
 +
 +  g_mutex_init (&allocator->lock);
 +  g_cond_init (&allocator->cond);
 +}
 +
 +GstOMXAllocator *
 +gst_omx_allocator_new (GstOMXComponent * component, GstOMXPort * port)
 +{
 +  GstOMXAllocator *allocator;
 +
 +  allocator = g_object_new (gst_omx_allocator_get_type (), NULL);
 +  allocator->component = gst_omx_component_ref (component);
 +  allocator->port = port;
 +
 +  return allocator;
 +}
 +
 +static void
 +gst_omx_allocator_finalize (GObject * object)
 +{
 +  GstOMXAllocator *allocator = GST_OMX_ALLOCATOR (object);
 +
 +  gst_omx_component_unref (allocator->component);
 +  g_mutex_clear (&allocator->lock);
 +  g_cond_clear (&allocator->cond);
 +
 +  G_OBJECT_CLASS (gst_omx_allocator_parent_class)->finalize (object);
 +}
 +
 +gboolean
 +gst_omx_allocator_configure (GstOMXAllocator * allocator, guint count,
 +    GstOMXAllocatorForeignMemMode mode)
 +{
 +  /* check if already configured */
 +  if (allocator->n_memories > 0)
 +    return FALSE;
 +
 +  allocator->n_memories = count;
 +  allocator->foreign_mode = mode;
 +  if (mode == GST_OMX_ALLOCATOR_FOREIGN_MEM_DMABUF)
 +    allocator->foreign_allocator = gst_dmabuf_allocator_new ();
++#ifdef TIZEN_FEATURE_OMX
++  else if (mode == GST_OMX_ALLOCATOR_FOREIGN_MEM_TBM)
++    allocator->foreign_allocator = gst_tizen_allocator_new ();
++#endif
 +
 +  return TRUE;
 +}
 +
 +/* must be protected with allocator->lock */
 +static void
 +gst_omx_allocator_dealloc (GstOMXAllocator * allocator)
 +{
 +  /* might be called more than once */
 +  if (!allocator->memories)
 +    return;
 +
 +  /* return foreign memory back to whoever lended it to us.
 +   * the signal handler is expected to increase the ref count of foreign_mem */
 +  if (allocator->foreign_mode == GST_OMX_ALLOCATOR_FOREIGN_MEM_OTHER_POOL) {
 +    gint i;
 +    GstOMXMemory *m;
 +
 +    for (i = 0; i < allocator->memories->len; i++) {
 +      m = g_ptr_array_index (allocator->memories, i);
 +
 +      /* this should not happen, but let's not crash for this */
 +      if (!m->foreign_mem) {
 +        GST_WARNING_OBJECT (allocator, "no foreign_mem to release");
 +        continue;
 +      }
 +
 +      /* restore the original dispose function */
 +      GST_MINI_OBJECT_CAST (m->foreign_mem)->dispose =
 +          (GstMiniObjectDisposeFunction) m->foreign_dispose;
 +
 +      g_signal_emit (allocator, signals[SIG_FOREIGN_MEM_RELEASED], 0, i,
 +          m->foreign_mem);
 +    }
 +  }
 +
 +  g_ptr_array_foreach (allocator->memories, (GFunc) gst_memory_unref, NULL);
 +  g_ptr_array_free (allocator->memories, TRUE);
 +  allocator->memories = NULL;
 +  allocator->n_memories = 0;
 +  allocator->foreign_mode = GST_OMX_ALLOCATOR_FOREIGN_MEM_NONE;
 +  if (allocator->foreign_allocator) {
 +    g_object_unref (allocator->foreign_allocator);
 +    allocator->foreign_allocator = NULL;
 +  }
 +
 +  g_cond_broadcast (&allocator->cond);
 +}
 +
 +gboolean
 +gst_omx_allocator_set_active (GstOMXAllocator * allocator, gboolean active)
 +{
 +  gboolean changed = FALSE;
 +
 +  /* on activation, _configure() must be called first */
 +  g_return_val_if_fail (!active || allocator->n_memories > 0, FALSE);
 +
 +  g_mutex_lock (&allocator->lock);
 +
 +  if (allocator->active != active)
 +    changed = TRUE;
 +
 +  if (changed) {
 +    if (active) {
 +      allocator->memories = g_ptr_array_sized_new (allocator->n_memories);
 +      g_ptr_array_set_size (allocator->memories, allocator->n_memories);
 +    } else {
 +      if (g_atomic_int_get (&allocator->n_outstanding) == 0)
 +        gst_omx_allocator_dealloc (allocator);
 +    }
 +  }
 +
 +  allocator->active = active;
 +  g_mutex_unlock (&allocator->lock);
 +
 +  return changed;
 +}
 +
 +void
 +gst_omx_allocator_wait_inactive (GstOMXAllocator * allocator)
 +{
 +  g_mutex_lock (&allocator->lock);
 +  while (allocator->memories)
 +    g_cond_wait (&allocator->cond, &allocator->lock);
 +  g_mutex_unlock (&allocator->lock);
 +}
 +
 +static inline void
 +dec_outstanding (GstOMXAllocator * allocator)
 +{
 +  if (g_atomic_int_dec_and_test (&allocator->n_outstanding)) {
 +    /* keep a ref to the allocator because _dealloc() will free
 +     * all the memories and the memories might be the only thing holding
 +     * a reference to the allocator; we need to keep it alive until the
 +     * end of this function call */
 +    g_object_ref (allocator);
 +
 +    /* take the lock so that _set_active() is not run concurrently */
 +    g_mutex_lock (&allocator->lock);
 +
 +    /* now that we have the lock, check if we have been de-activated with
 +     * outstanding buffers */
 +    if (!allocator->active)
 +      gst_omx_allocator_dealloc (allocator);
 +
 +    g_mutex_unlock (&allocator->lock);
 +    g_object_unref (allocator);
 +  }
 +}
 +
 +GstFlowReturn
 +gst_omx_allocator_acquire (GstOMXAllocator * allocator, GstMemory ** memory,
 +    gint index, GstOMXBuffer * omx_buf)
 +{
 +  GstFlowReturn ret = GST_FLOW_OK;
 +  GstOMXMemory *omx_mem = NULL;
 +
 +  /* ensure memories are not going to disappear concurrently */
 +  g_atomic_int_inc (&allocator->n_outstanding);
 +
 +  if (!allocator->active) {
 +    ret = GST_FLOW_FLUSHING;
 +    goto beach;
 +  }
 +
 +  if (index >= 0 && index < allocator->n_memories)
 +    omx_mem = g_ptr_array_index (allocator->memories, index);
 +  else if (omx_buf) {
 +    for (index = 0; index < allocator->n_memories; index++) {
 +      omx_mem = g_ptr_array_index (allocator->memories, index);
 +      if (omx_mem->buf == omx_buf)
 +        break;
 +    }
 +  }
 +
 +  if (G_UNLIKELY (!omx_mem || index >= allocator->n_memories)) {
 +    GST_ERROR_OBJECT (allocator, "Failed to find OMX memory");
 +    ret = GST_FLOW_ERROR;
 +    goto beach;
 +  }
 +
 +  if (G_UNLIKELY (omx_mem->buf->used)) {
 +    GST_ERROR_OBJECT (allocator,
 +        "Trying to acquire a buffer that is being used by the OMX port");
 +    ret = GST_FLOW_ERROR;
 +    goto beach;
 +  }
 +
 +  omx_mem->acquired = TRUE;
 +
 +  if (omx_mem->foreign_mem)
 +    *memory = omx_mem->foreign_mem;
 +  else
 +    *memory = GST_MEMORY_CAST (omx_mem);
 +
 +beach:
 +  if (ret != GST_FLOW_OK)
 +    dec_outstanding (allocator);
 +  return ret;
 +}
 +
++#ifdef TIZEN_FEATURE_OMX
++static void
++_destroy_tbm_surface (tbm_surface_h surface)
++{
++  GST_DEBUG ("destroy surface %p", surface);
++  tbm_surface_internal_destroy (surface);
++}
++#endif
++
 +/* installed as the GstMiniObject::dispose function of the acquired GstMemory */
 +static gboolean
 +gst_omx_allocator_memory_dispose (GstMemory * mem)
 +{
 +  GstOMXMemory *omx_mem;
 +  GstOMXAllocator *allocator;
 +
 +  /* memory may be from our allocator, but
 +   * may as well be from the dmabuf allocator */
 +  if (GST_IS_OMX_ALLOCATOR (mem->allocator))
 +    omx_mem = (GstOMXMemory *) mem;
 +  else
 +    omx_mem = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
 +        GST_OMX_MEMORY_QUARK);
 +
 +  if (omx_mem->acquired) {
 +    /* keep the memory alive */
 +    gst_memory_ref (mem);
 +
 +    omx_mem->acquired = FALSE;
 +
 +    allocator = GST_OMX_ALLOCATOR (GST_MEMORY_CAST (omx_mem)->allocator);
 +
 +    /* inform the upper layer that we are no longer using this GstOMXBuffer */
 +    g_signal_emit (allocator, signals[SIG_OMXBUF_RELEASED], 0, omx_mem->buf);
 +
 +    dec_outstanding (allocator);
 +
 +    /* be careful here, both the memory and the allocator
 +     * may have been free'd as part of the call to dec_outstanding() */
 +
 +    return FALSE;
 +  }
 +
 +  /* if the foreign memory had a dispose function, let that one decide
 +   * the fate of this memory. We are no longer going to be using it here */
 +  if (omx_mem->foreign_dispose)
 +    return omx_mem->foreign_dispose (GST_MINI_OBJECT_CAST (mem));
 +
 +  return TRUE;
 +}
 +
 +static inline void
 +install_mem_dispose (GstOMXMemory * mem)
 +{
 +  GstMemory *managed_mem = (GstMemory *) mem;
 +
 +  if (mem->foreign_mem) {
 +    managed_mem = mem->foreign_mem;
 +    mem->foreign_dispose = GST_MINI_OBJECT_CAST (managed_mem)->dispose;
 +  }
 +
 +  GST_MINI_OBJECT_CAST (managed_mem)->dispose =
 +      (GstMiniObjectDisposeFunction) gst_omx_allocator_memory_dispose;
 +}
 +
 +/* the returned memory is transfer:none, ref still belongs to the allocator */
 +GstMemory *
 +gst_omx_allocator_allocate (GstOMXAllocator * allocator, gint index,
 +    GstMemory * foreign_mem)
 +{
 +  GstOMXMemory *mem;
 +  GstOMXBuffer *omx_buf;
 +
 +  g_return_val_if_fail (allocator->port->buffers, NULL);
 +  g_return_val_if_fail (allocator->memories, NULL);
 +  g_return_val_if_fail (index >= 0 && index < allocator->n_memories, NULL);
 +  g_return_val_if_fail ((foreign_mem == NULL &&
 +          allocator->foreign_mode != GST_OMX_ALLOCATOR_FOREIGN_MEM_OTHER_POOL)
 +      || (foreign_mem != NULL
 +          && allocator->foreign_mode ==
 +          GST_OMX_ALLOCATOR_FOREIGN_MEM_OTHER_POOL), NULL);
 +
 +  omx_buf = g_ptr_array_index (allocator->port->buffers, index);
 +  g_return_val_if_fail (omx_buf != NULL, NULL);
 +
 +  mem = gst_omx_memory_new (allocator, omx_buf, 0, NULL, 0, -1);
 +
 +  switch (allocator->foreign_mode) {
 +    case GST_OMX_ALLOCATOR_FOREIGN_MEM_NONE:
 +      install_mem_dispose (mem);
 +      break;
 +    case GST_OMX_ALLOCATOR_FOREIGN_MEM_DMABUF:
 +    {
 +      gint fd = GPOINTER_TO_INT (omx_buf->omx_buf->pBuffer);
 +      mem->foreign_mem =
 +          gst_dmabuf_allocator_alloc (allocator->foreign_allocator, fd,
 +          omx_buf->omx_buf->nAllocLen);
 +      gst_mini_object_set_qdata (GST_MINI_OBJECT (mem->foreign_mem),
 +          GST_OMX_MEMORY_QUARK, mem, NULL);
 +      install_mem_dispose (mem);
 +      break;
 +    }
++#ifdef TIZEN_FEATURE_OMX
++    case GST_OMX_ALLOCATOR_FOREIGN_MEM_TBM:
++    {
++      tbm_surface_h surface = (tbm_surface_h) omx_buf->omx_buf->pBuffer;
++      mem->foreign_mem = gst_tizen_allocator_alloc_surface (allocator->foreign_allocator,
++        &allocator->video_info, surface, omx_buf, (GDestroyNotify)_destroy_tbm_surface);
++      break;
++    }
++#endif
 +    case GST_OMX_ALLOCATOR_FOREIGN_MEM_OTHER_POOL:
 +      mem->foreign_mem = foreign_mem;
 +      gst_mini_object_set_qdata (GST_MINI_OBJECT (mem->foreign_mem),
 +          GST_OMX_MEMORY_QUARK, mem, NULL);
 +      install_mem_dispose (mem);
 +      break;
 +    default:
 +      g_assert_not_reached ();
 +      break;
 +  }
 +
 +  g_ptr_array_index (allocator->memories, index) = mem;
 +  return mem->foreign_mem ? mem->foreign_mem : (GstMemory *) mem;
 +}
 +
 +static void
 +gst_omx_allocator_free (GstAllocator * allocator, GstMemory * mem)
 +{
 +  GstOMXMemory *omem = (GstOMXMemory *) mem;
 +
 +  g_warn_if_fail (!omem->acquired);
 +
 +  if (omem->foreign_mem)
 +    gst_memory_unref (omem->foreign_mem);
 +
 +  g_slice_free (GstOMXMemory, omem);
 +}
 +
 +static void
 +gst_omx_allocator_class_init (GstOMXAllocatorClass * klass)
 +{
 +  GObjectClass *object_class;
 +  GstAllocatorClass *allocator_class;
 +
 +  object_class = (GObjectClass *) klass;
 +  allocator_class = (GstAllocatorClass *) klass;
 +
 +  object_class->finalize = gst_omx_allocator_finalize;
 +  allocator_class->alloc = NULL;
 +  allocator_class->free = gst_omx_allocator_free;
 +
 +  signals[SIG_OMXBUF_RELEASED] = g_signal_new ("omxbuf-released",
 +      G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0,
 +      NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER);
 +
 +  signals[SIG_FOREIGN_MEM_RELEASED] = g_signal_new ("foreign-mem-released",
 +      G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0,
 +      NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER);
 +}
index 5c94584,0000000..a03a904
mode 100644,000000..100644
--- /dev/null
@@@ -1,114 -1,0 +1,121 @@@
 +/*
 + * Copyright (C) 2019, Collabora Ltd.
 + *   Author: George Kiagiadakis <george.kiagiadakis@collabora.com>
 + *
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation
 + * version 2.1 of the License.
 + *
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with this library; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 + *
 + */
 +
 +#ifndef __GST_OMX_ALLOCATOR_H__
 +#define __GST_OMX_ALLOCATOR_H__
 +
 +#ifdef HAVE_CONFIG_H
 +#include "config.h"
 +#endif
 +
 +#include <gst/gst.h>
 +
 +#include "gstomx.h"
 +
 +G_BEGIN_DECLS
 +
 +#define GST_OMX_MEMORY_QUARK gst_omx_memory_quark ()
 +
 +#define GST_TYPE_OMX_ALLOCATOR   (gst_omx_allocator_get_type())
 +#define GST_IS_OMX_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OMX_ALLOCATOR))
 +#define GST_OMX_ALLOCATOR(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_OMX_ALLOCATOR, GstOMXAllocator))
 +
 +typedef struct _GstOMXMemory GstOMXMemory;
 +typedef struct _GstOMXAllocator GstOMXAllocator;
 +typedef struct _GstOMXAllocatorClass GstOMXAllocatorClass;
 +
 +typedef enum {
 +  GST_OMX_ALLOCATOR_FOREIGN_MEM_NONE,
 +  GST_OMX_ALLOCATOR_FOREIGN_MEM_DMABUF,
++#ifdef TIZEN_FEATURE_OMX
++  GST_OMX_ALLOCATOR_FOREIGN_MEM_TBM,
++#endif
 +  GST_OMX_ALLOCATOR_FOREIGN_MEM_OTHER_POOL,
 +} GstOMXAllocatorForeignMemMode;
 +
 +struct _GstOMXMemory
 +{
 +  GstMemory mem;
 +  GstOMXBuffer *buf;
 +
 +  /* TRUE if the memory is in use outside the allocator */
 +  gboolean acquired;
 +
 +  /* memory allocated from the foreign_allocator
 +   * or planted externally when using a foreign buffer pool */
 +  GstMemory *foreign_mem;
++
 +  /* the original dispose function of foreign_mem */
 +  GstMiniObjectDisposeFunction foreign_dispose;
 +};
 +
 +struct _GstOMXAllocator
 +{
 +  GstAllocator parent;
 +
 +  GstOMXComponent *component;
 +  GstOMXPort *port;
 +
 +  GstOMXAllocatorForeignMemMode foreign_mode;
 +  GstAllocator *foreign_allocator;
 +
 +  /* array of GstOMXMemory */
 +  GPtrArray *memories;
 +  guint n_memories;
 +
 +  guint n_outstanding;
 +  gboolean active;
 +
 +  GMutex lock;
 +  GCond cond;
++#ifdef TIZEN_FEATURE_OMX
++  GstVideoInfo video_info;
++#endif
 +};
 +
 +struct _GstOMXAllocatorClass
 +{
 +  GstAllocatorClass parent_class;
 +};
 +
 +GType gst_omx_allocator_get_type (void);
 +
 +GQuark gst_omx_memory_quark (void);
 +
 +GstOMXBuffer * gst_omx_memory_get_omx_buf (GstMemory * mem);
 +
 +GstOMXAllocator * gst_omx_allocator_new (GstOMXComponent * component,
 +    GstOMXPort * port);
 +
 +gboolean gst_omx_allocator_configure (GstOMXAllocator * allocator, guint count,
 +    GstOMXAllocatorForeignMemMode mode);
 +gboolean gst_omx_allocator_set_active (GstOMXAllocator * allocator,
 +    gboolean active);
 +void gst_omx_allocator_wait_inactive (GstOMXAllocator * allocator);
 +
 +GstFlowReturn gst_omx_allocator_acquire (GstOMXAllocator * allocator,
 +    GstMemory ** memory, gint index, GstOMXBuffer * omx_buf);
 +
 +GstMemory * gst_omx_allocator_allocate (GstOMXAllocator * allocator, gint index,
 +    GstMemory * foreign_mem);
 +
 +G_END_DECLS
 +
 +#endif
@@@ -41,6 -43,226 +41,60 @@@ enu
  
  static guint signals[LAST_SIGNAL] = { 0 };
  
 -struct _GstOMXMemory
 -{
 -#ifdef TIZEN_FEATURE_OMX
 -  GstTizenMemory mem;
 -#else
 -  GstMemory mem;
 -#endif
 -
 -  GstOMXBuffer *buf;
 -};
 -
 -struct _GstOMXMemoryAllocator
 -{
 -  GstAllocator parent;
 -};
 -
 -struct _GstOMXMemoryAllocatorClass
 -{
 -  GstAllocatorClass parent_class;
 -};
 -
 -#define GST_OMX_MEMORY_TYPE "openmax"
 -
 -static GstMemory *
 -gst_omx_memory_allocator_alloc_dummy (GstAllocator * allocator, gsize size,
 -    GstAllocationParams * params)
 -{
 -  g_assert_not_reached ();
 -  return NULL;
 -}
 -
 -static void
 -gst_omx_memory_allocator_free (GstAllocator * allocator, GstMemory * mem)
 -{
 -  GstOMXMemory *omem = (GstOMXMemory *) mem;
 -
 -  /* TODO: We need to remember which memories are still used
 -   * so we can wait until everything is released before allocating
 -   * new memory
 -   */
 -
 -  g_slice_free (GstOMXMemory, omem);
 -}
 -
 -#ifdef TIZEN_FEATURE_OMX
 -static void
 -_destroy_tbm_surface (tbm_surface_h surface)
 -{
 -  GST_DEBUG ("destroy surface %p", surface);
 -  tbm_surface_internal_destroy (surface);
 -}
 -#endif
 -
 -static gpointer
 -gst_omx_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
 -{
 -#ifdef TIZEN_FEATURE_OMX
 -  int err;
 -  gpointer data = NULL;
 -  tbm_surface_info_s info;
 -  GstTizenMemory *tmem = (GstTizenMemory *)mem;
 -
 -  g_mutex_lock (&tmem->lock);
 -  err = tbm_surface_map (tmem->surface, TBM_SURF_OPTION_WRITE|TBM_SURF_OPTION_READ, &info);
 -  if (err == TBM_SURFACE_ERROR_NONE)
 -    data = info.planes[0].ptr;
 -  g_mutex_unlock (&tmem->lock);
 -
 -  return data;
 -#else
 -  GstOMXMemory *omem = (GstOMXMemory *) mem;
 -
 -  return omem->buf->omx_buf->pBuffer + omem->mem.offset;
 -#endif
 -}
 -
 -static void
 -gst_omx_memory_unmap (GstMemory * mem)
 -{
 -#ifdef TIZEN_FEATURE_OMX
 -  GstTizenMemory *tmem = (GstTizenMemory *)mem;
 -
 -  g_mutex_lock (&tmem->lock);
 -  tbm_surface_unmap (tmem->surface);
 -  g_mutex_unlock (&tmem->lock);
 -#endif
 -}
 -
 -static GstMemory *
 -gst_omx_memory_share (GstMemory * mem, gssize offset, gssize size)
 -{
 -  g_assert_not_reached ();
 -  return NULL;
 -}
 -
+ #ifdef TIZEN_FEATURE_OMX
+ gboolean
+ gst_omx_video_memory_map (GstVideoMeta * meta, guint plane, GstMapInfo * info,
+     gpointer * data, gint * stride, GstMapFlags flags)
+ {
+   gint err;
+   tbm_surface_info_s surface_info;
+   GstBuffer *buffer = meta->buffer;
+   GstMemory *mem = gst_buffer_peek_memory (buffer, 0);
+   if (!gst_is_tizen_memory (mem)) {
+     GST_ERROR ("Invalid memory");
+     return FALSE;
+   }
+   err = tbm_surface_map (((GstTizenMemory *)mem)->surface, TBM_SURF_OPTION_WRITE|TBM_SURF_OPTION_READ, &surface_info);
+   if (err != TBM_SURFACE_ERROR_NONE) {
+     GST_ERROR ("Failed to map memory");
+     return FALSE;
+   }
+   tbm_surface_unmap (((GstTizenMemory *)mem)->surface);
+   if (surface_info.num_planes <= plane) {
+     GST_ERROR ("Invalid format");
+     return FALSE;
+   }
+   *data = surface_info.planes[plane].ptr;
+   *stride = surface_info.planes[plane].stride;
+   GST_DEBUG ("_video_memory_map -> plane : %d, data : %p, stride : %d",
+       plane, *data, *stride);
+   return TRUE;
+ }
+ gboolean
+ gst_omx_video_memory_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info)
+ {
+   GstBuffer *buffer = meta->buffer;
+   GstMemory *mem = gst_buffer_peek_memory (buffer, 0);
+   if (!gst_is_tizen_memory (mem)) {
+     GST_ERROR ("Invalid memory");
+     return FALSE;
+   }
+   GST_DEBUG ("_video_memory_unmap -> plane : %d", plane);
+   return TRUE;
+ }
+ #endif
 -GType gst_omx_memory_allocator_get_type (void);
 -G_DEFINE_TYPE (GstOMXMemoryAllocator, gst_omx_memory_allocator,
 -    GST_TYPE_ALLOCATOR);
 -
 -#define GST_TYPE_OMX_MEMORY_ALLOCATOR   (gst_omx_memory_allocator_get_type())
 -#define GST_IS_OMX_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OMX_MEMORY_ALLOCATOR))
 -
 -static void
 -gst_omx_memory_allocator_class_init (GstOMXMemoryAllocatorClass * klass)
 -{
 -  GstAllocatorClass *allocator_class;
 -
 -  allocator_class = (GstAllocatorClass *) klass;
 -
 -  allocator_class->alloc = gst_omx_memory_allocator_alloc_dummy;
 -  allocator_class->free = gst_omx_memory_allocator_free;
 -}
 -
 -static void
 -gst_omx_memory_allocator_init (GstOMXMemoryAllocator * allocator)
 -{
 -  GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
 -
 -  alloc->mem_type = GST_OMX_MEMORY_TYPE;
 -  alloc->mem_map = gst_omx_memory_map;
 -  alloc->mem_unmap = gst_omx_memory_unmap;
 -  alloc->mem_share = gst_omx_memory_share;
 -
 -  /* default copy & is_span */
 -
 -  GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
 -}
 -
 -#ifndef TIZEN_FEATURE_OMX
 -static GstMemory *
 -gst_omx_memory_allocator_alloc (GstAllocator * allocator, GstMemoryFlags flags,
 -    GstOMXBuffer * buf)
 -{
 -  GstOMXMemory *mem;
 -  gint align;
 -
 -  /* FIXME: We don't allow sharing because we need to know
 -   * when the memory becomes unused and can only then put
 -   * it back to the pool. Which is done in the pool's release
 -   * function
 -   */
 -  flags |= GST_MEMORY_FLAG_NO_SHARE;
 -
 -  /* GStreamer uses a bitmask for the alignment while
 -   * OMX uses the alignment itself. So we have to convert
 -   * here */
 -  align = buf->port->port_def.nBufferAlignment;
 -  if (align > 0)
 -    align -= 1;
 -  if (((align + 1) & align) != 0) {
 -    GST_WARNING ("Invalid alignment that is not a power of two: %u",
 -        (guint) buf->port->port_def.nBufferAlignment);
 -    align = 0;
 -  }
 -
 -  mem = g_slice_new (GstOMXMemory);
 -  /* the shared memory is always readonly */
 -  gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, NULL,
 -      buf->omx_buf->nAllocLen, align, 0, buf->omx_buf->nAllocLen);
 -
 -  mem->buf = buf;
 -
 -  return GST_MEMORY_CAST (mem);
 -}
 -#endif
 -
  /* Buffer pool for the buffers of an OpenMAX port.
   *
   * This pool is only used if we either passed buffers from another
@@@ -347,8 -546,49 +411,13 @@@ gst_omx_buffer_pool_alloc_buffer (GstBu
      const guint nslice = pool->port->port_def.format.video.nSliceHeight;
      gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
      gint stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
+ #ifdef TIZEN_FEATURE_OMX
+     tbm_surface_h surface = NULL;
+     uint32_t _offset = 0;
+     uint32_t _stride = 0;
+ #endif
  
 -    if (pool->output_mode == GST_OMX_BUFFER_MODE_DMABUF) {
 -      gint fd;
 -      GstMapInfo map;
 -
 -      fd = GPOINTER_TO_INT (omx_buf->omx_buf->pBuffer);
 -
 -      mem =
 -          gst_dmabuf_allocator_alloc (pool->allocator, fd,
 -          omx_buf->omx_buf->nAllocLen);
 -
 -      if (!gst_caps_features_contains (gst_caps_get_features (pool->caps, 0),
 -              GST_CAPS_FEATURE_MEMORY_DMABUF)) {
 -        /* Check if the memory is actually mappable */
 -        if (!gst_memory_map (mem, &map, GST_MAP_READWRITE)) {
 -          GST_ERROR_OBJECT (pool,
 -              "dmabuf memory is not mappable but caps does not have the 'memory:DMABuf' feature");
 -          gst_memory_unref (mem);
 -          return GST_FLOW_ERROR;
 -        }
 -
 -        gst_memory_unmap (mem, &map);
 -      }
 -#ifdef TIZEN_FEATURE_OMX
 -    } else {
 -      surface = (tbm_surface_h) omx_buf->omx_buf->pBuffer;
 -
 -      mem = gst_tizen_allocator_alloc_surface (pool->allocator, &pool->video_info,
 -        surface, omx_buf, (GDestroyNotify)_destroy_tbm_surface);
 -#else
 -    } else {
 -      mem = gst_omx_memory_allocator_alloc (pool->allocator, 0, omx_buf);
 -#endif
 -    }
 -
      buf = gst_buffer_new ();
 -    gst_buffer_append_memory (buf, mem);
 -    g_ptr_array_add (pool->buffers, buf);
  
      switch (GST_VIDEO_INFO_FORMAT (&pool->video_info)) {
        case GST_VIDEO_FORMAT_ABGR:
            GST_VIDEO_INFO_WIDTH (&pool->video_info),
            GST_VIDEO_INFO_HEIGHT (&pool->video_info),
            GST_VIDEO_INFO_N_PLANES (&pool->video_info), offset, stride);
 +
 +      if (gst_omx_video_get_port_padding (pool->port, &pool->video_info,
 +              &align))
 +        gst_video_meta_set_alignment (meta, align);
+ #ifdef TIZEN_FEATURE_OMX
+       meta->map = gst_omx_video_memory_map;
+       meta->unmap = gst_omx_video_memory_unmap;
+ #endif
      }
    }
  
@@@ -663,12 -877,23 +746,15 @@@ gst_omx_buffer_pool_new (GstElement * e
    pool->component = gst_omx_component_ref (component);
    pool->port = port;
    pool->output_mode = output_mode;
 -
 -  switch (output_mode) {
 -    case GST_OMX_BUFFER_MODE_DMABUF:
 -      pool->allocator = gst_dmabuf_allocator_new ();
 -      break;
 -    case GST_OMX_BUFFER_MODE_SYSTEM_MEMORY:
 -      pool->allocator =
 -          g_object_new (gst_omx_memory_allocator_get_type (), NULL);
 -      break;
 +  pool->allocator = gst_omx_allocator_new (component, port);
+ #ifdef TIZEN_FEATURE_OMX
 -    case GST_OMX_BUFFER_MODE_TBM:
 -      pool->allocator = gst_tizen_allocator_new ();
 -      break;
++  pool->allocator->video_info = pool->video_info;
+ #endif
 -    default:
 -      g_assert_not_reached ();
 -  }
 +
 +  g_signal_connect_object (pool->allocator, "omxbuf-released",
 +      (GCallback) on_allocator_omxbuf_released, pool, 0);
 +  g_signal_connect_object (pool->allocator, "foreign-mem-released",
 +      (GCallback) on_allocator_foreign_mem_released, pool, 0);
  
    return GST_BUFFER_POOL (pool);
  }
Simple merge
@@@ -50,21 -50,6 +50,30 @@@ enu
  G_DEFINE_TYPE_WITH_CODE (GstOMXH264Dec, gst_omx_h264_dec,
      GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
  
++#ifdef TIZEN_FEATURE_OMX
++#define MAKE_CAPS(alignment) \
++  "video/x-h264, " \
++      "alignment=(string) " alignment ", " \
++      "stream-format=(string) byte-stream, " \
++      "width=(int) [1,MAX], height=(int) [1,MAX], " \
++      "framerate = (fraction) [0/1, MAX]"
++#else
 +#define MAKE_CAPS(alignment) \
 +  "video/x-h264, " \
 +      "alignment=(string) " alignment ", " \
 +      "stream-format=(string) byte-stream, " \
 +      "width=(int) [1,MAX], height=(int) [1,MAX]"
++#endif
 +
 +/* The Zynq supports decoding subframes, though we want "au" to be the
 + * default, so we keep it prepended. This is the only way that it works with
 + * rtph264depay. */
 +#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
 +#define SINK_CAPS MAKE_CAPS ("au") ";" MAKE_CAPS ("nal")
 +#else
 +#define SINK_CAPS MAKE_CAPS ("au")
 +#endif
 +
  static void
  gst_omx_h264_dec_class_init (GstOMXH264DecClass * klass)
  {
@@@ -68,15 -71,15 +72,21 @@@ enu
  #ifdef USE_OMX_TARGET_RPI
  #define GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT      TRUE
  #endif
+ #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
+ #define GST_OMX_VIDEO_ENC_NUM_REF_FRAME_DEFAULT (0x00000001)
+ #define GST_OMX_VIDEO_ENC_NUM_REF_FRAME_MAX (0x00000002)
+ #define GST_OMX_VIDEO_ENC_NUM_B_FRAME_DEFAULT (0x00000001)
+ #define GST_OMX_VIDEO_ENC_NUM_B_FRAME_MAX (0x00000002)
+ #endif
  #define GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT    (0xffffffff)
  #define GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT (0xffffffff)
 +#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
 +#define GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT (0)
 +#define ALIGNMENT "{ au, nal }"
 +#else
  #define GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT (0xffffffff)
 +#define ALIGNMENT "au"
 +#endif
  #define GST_OMX_H264_VIDEO_ENC_ENTROPY_MODE_DEFAULT (0xffffffff)
  #define GST_OMX_H264_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT (FALSE)
  #define GST_OMX_H264_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT (0xffffffff)
Simple merge
Simple merge
@@@ -541,11 -638,12 +643,13 @@@ gst_omx_video_dec_fill_buffer (GstOMXVi
    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) {
 +      GST_VIDEO_INFO_FIELD_HEIGHT (vinfo) !=
 +      port_def->format.video.nFrameHeight) {
      GST_ERROR_OBJECT (self, "Resolution do not match: port=%ux%u vinfo=%dx%d",
          (guint) port_def->format.video.nFrameWidth,
          (guint) port_def->format.video.nFrameHeight,
      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, };
 +        { GST_VIDEO_INFO_FIELD_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;
          dst_width[1] = dst_width[0];
          src_stride[1] = nstride;
          src_size[1] = src_stride[1] * nslice;
 -        dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo);
 +        dst_height[1] = GST_VIDEO_INFO_FIELD_HEIGHT (vinfo);
          break;
+ #endif
+ #ifdef TIZEN_FEATURE_OMX
+       case GST_VIDEO_FORMAT_SN12:
+       case GST_VIDEO_FORMAT_ST12:
+         ret = TRUE;
+         break;
+ #endif
        default:
          g_assert_not_reached ();
          break;
@@@ -1777,9 -1795,14 +1927,16 @@@ gst_omx_video_dec_loop (GstOMXVideoDec 
        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 {
 +      GstVideoInterlaceMode interlace_mode;
 +
        /* Just update caps */
        GST_VIDEO_DECODER_STREAM_LOCK (self);
  
@@@ -2994,9 -2951,16 +3185,16 @@@ gst_omx_video_dec_handle_frame (GstVide
    }
  
    if (!self->started) {
 -    if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
 +    if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame) && !header) {
+ #ifdef TIZEN_FEATURE_OMX
+       if (!self->codec_data) {
 -#endif /* TIZEN_FEATURE_OMX */
++#endif
        gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
        return GST_FLOW_OK;
 -#endif /* TIZEN_FEATURE_OMX */
+ #ifdef TIZEN_FEATURE_OMX
+       }
+       GST_WARNING_OBJECT (self, "Not I frame[%"GST_TIME_FORMAT"], but keep going...", GST_TIME_ARGS (frame->pts));
++#endif
      }
  
      if (gst_omx_port_is_flushing (self->dec_out_port)) {
        }
  
        buf->omx_buf->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
 -      buf->omx_buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
  
+ #ifdef CODEC_DEC_INTPUT_DUMP
+       decoder_input_dump (buf, port->use_buffer);
+ #endif
        if (GST_CLOCK_TIME_IS_VALID (timestamp))
          GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
              gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND,
@@@ -3472,6 -3432,10 +3678,10 @@@ gst_omx_video_dec_decide_allocation (Gs
    i = 0;
    while (i < gst_query_get_n_allocation_pools (query)) {
      gst_query_parse_nth_allocation_pool (query, i, &pool, NULL, NULL, NULL);
 -#else /* TIZEN_FEATURE_OMX */
+ #ifdef TIZEN_FEATURE_OMX
+     gst_query_remove_nth_allocation_pool (query, i);
+     GST_WARNING_OBJECT (self, "remove pool from downstream %u", gst_query_get_n_allocation_pools (query));
++#else
      if (GST_IS_OMX_BUFFER_POOL (pool)) {
        GST_DEBUG_OBJECT (self, "Discard OMX pool from downstream");
        gst_query_remove_nth_allocation_pool (query, i);
        self->use_buffers = TRUE;
        i++;
      }
 -#endif /* TIZEN_FEATURE_OMX */
++#endif
  
      if (pool)
        gst_object_unref (pool);
@@@ -307,14 -291,8 +313,15 @@@ enu
  #define GST_OMX_VIDEO_ENC_SLICE_SIZE_DEFAULT (0)
  #define GST_OMX_VIDEO_ENC_DEPENDENT_SLICE_DEFAULT (FALSE)
  #define GST_OMX_VIDEO_ENC_DEFAULT_ROI_QUALITY OMX_ALG_ROI_QUALITY_HIGH
 +#define GST_OMX_VIDEO_ENC_LONGTERM_REF_DEFAULT (FALSE)
 +#define GST_OMX_VIDEO_ENC_LONGTERM_FREQUENCY_DEFAULT (0)
 +#define GST_OMX_VIDEO_ENC_LOOK_AHEAD_DEFAULT (0)
 +
 +/* ZYNQ_USCALE_PLUS encoder custom events */
 +#define OMX_ALG_GST_EVENT_INSERT_LONGTERM "omx-alg/insert-longterm"
 +#define OMX_ALG_GST_EVENT_USE_LONGTERM "omx-alg/use-longterm"
  
  /* class initialization */
  #define do_init \
  { \
@@@ -1051,6 -960,37 +1090,37 @@@ gst_omx_video_enc_open (GstVideoEncode
      return FALSE;
  #endif
  
 -#endif /* USE_OMX_TARGET_EXYNOS || USE_OMX_TARGET_EXYNOS64 */
 -#endif /* TIZEN_FEATURE_OMX */
+ #ifdef TIZEN_FEATURE_OMX
+   self->enc_in_port->use_buffer = klass->cdata.in_port_usebuffer;
+   self->enc_out_port->use_buffer = klass->cdata.out_port_usebuffer;
+   /* get extension index and set platform specific buffer enable */
+ #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
+   {
+     OMX_ERRORTYPE err;
+     OMX_INDEXTYPE index = OMX_IndexComponentStartUnused;
+     EnableGemBuffersParams gem_param;
+     err = gst_omx_component_get_extension_index (self->enc, (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 = 0;
+     err = gst_omx_component_set_parameter (self->enc, 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);
+     }
+   }
++#endif
++#endif
    return TRUE;
  }
  
@@@ -1481,8 -1434,8 +1582,9 @@@ gst_omx_video_enc_handle_output_frame (
            "Downstream element refused to negotiate codec_data in the caps");
        return GST_FLOW_NOT_NEGOTIATED;
      }
 +    gst_video_codec_frame_unref (frame);
      flow_ret = GST_FLOW_OK;
+ #endif
    } else if (buf->omx_buf->nFilledLen > 0) {
      GstBuffer *outbuf;
      GstMapInfo map = GST_MAP_INFO_INIT;
@@@ -1671,8 -1604,12 +1773,12 @@@ gst_omx_video_enc_loop (GstOMXVideoEnc 
        err = gst_omx_port_set_enabled (port, TRUE);
        if (err != OMX_ErrorNone)
          goto reconfigure_error;
 -    err = gst_omx_port_tbm_allocate_enc_buffers (port);
 +
+ #ifdef TIZEN_FEATURE_OMX
 -      err = gst_omx_port_allocate_buffers (port);
++      if (!gst_omx_port_tbm_allocate_enc_buffers (port))
+ #else
 -      if (err != OMX_ErrorNone)
 +      if (!gst_omx_video_enc_allocate_out_buffers (self))
+ #endif
          goto reconfigure_error;
  
        err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
@@@ -2826,10 -2639,10 +2932,11 @@@ gst_omx_video_enc_fill_buffer (GstOMXVi
      goto done;
    }
  
+ #ifndef TIZEN_FEATURE_OMX
    /* Same strides and everything */
 -  if (gst_buffer_get_size (inbuf) ==
 -      outbuf->omx_buf->nAllocLen - outbuf->omx_buf->nOffset) {
 +  if ((gst_buffer_get_size (inbuf) ==
 +          outbuf->omx_buf->nAllocLen - outbuf->omx_buf->nOffset) &&
 +      (stride == port_def->format.video.nStride)) {
      outbuf->omx_buf->nFilledLen = gst_buffer_get_size (inbuf);
  
      GST_LOG_OBJECT (self, "Matched strides - direct copy %u bytes",
            gst_omx_video_enc_semi_planar_manual_copy (self, inbuf, outbuf,
            info->finfo);
        break;
 -#endif /* CODEC_ENC_INPUT_DUMP */
 +    case GST_VIDEO_FORMAT_GRAY8:
 +    {
 +      if (!gst_video_frame_map (&frame, info, inbuf, GST_MAP_READ)) {
 +        GST_ERROR_OBJECT (self, "Failed to map input buffer");
 +        ret = FALSE;
 +        goto done;
 +      }
 +
 +      ret = gst_omx_video_enc_copy_plane (self, 0, &frame, outbuf, info->finfo);
 +      gst_video_frame_unmap (&frame);
 +    }
 +      break;
+ #ifdef TIZEN_FEATURE_OMX
+     case GST_VIDEO_FORMAT_ST12:
+     case GST_VIDEO_FORMAT_SN12: {
+       tbm_surface_h surface;
+       GstMemory *mem = gst_buffer_peek_memory (inbuf, 0);
+       if (!gst_is_tizen_memory (mem)) {
+         GST_ERROR_OBJECT (self, "Invalid input buffer");
+         ret = FALSE;
+         break;
+       }
+       if (!(surface = gst_tizen_memory_get_surface (mem))) {
+         GST_ERROR_OBJECT (self, "Failed to get surface from tizen memory");
+         ret = FALSE;
+         break;
+       }
+       outbuf->omx_buf->pBuffer = (OMX_U8 *) surface;
+       outbuf->omx_buf->nAllocLen = (OMX_U32) tbm_surface_internal_get_size (surface);
+       outbuf->omx_buf->nFilledLen = (OMX_U32) tbm_surface_internal_get_size (surface);
+ #ifdef CODEC_ENC_INPUT_DUMP
+       gst_omx_video_enc_input_dump (inbuf);
 -#endif /* TIZEN_FEATURE_OMX */
++#endif
+       ret = TRUE;
+       break;
+     }
++#endif
      default:
        GST_ERROR_OBJECT (self, "Unsupported format");
        goto done;
@@@ -3542,6 -3340,10 +3677,10 @@@ filter_supported_formats (GList * negot
      GList *next;
  
      switch (nmap->format) {
 -#endif /* TIZEN_FEATURE_OMX */
+ #ifdef TIZEN_FEATURE_OMX
+       case GST_VIDEO_FORMAT_SN12:
+       case GST_VIDEO_FORMAT_ST12:
++#endif
        case GST_VIDEO_FORMAT_I420:
        case GST_VIDEO_FORMAT_NV12:
        case GST_VIDEO_FORMAT_NV12_10LE32:
diff --cc omx/meson.build
@@@ -33,6 -32,6 +33,10 @@@ if have_omx_vp
    omx_sources += 'gstomxvp8dec.c'
  endif
  
++if have_omx_vp9
++  omx_sources += 'gstomxvp9dec.c'
++endif
++
  if have_omx_theora
    omx_sources += 'gstomxtheoradec.c'
  endif
@@@ -55,9 -54,7 +59,9 @@@ gstomx = library('gstomx'
  #  link_args : noseh_link_args,
    include_directories : [configinc, omx_inc],
    dependencies : [gstvideo_dep, gstaudio_dep, gstbase_dep, gstcontroller_dep,
--                  libm, gmodule_dep, gstallocators_dep] + optional_deps,
++                  libm, gmodule_dep, gstallocators_dep, tbm_dep] + optional_deps,
    install : true,
    install_dir : plugins_install_dir,
  )
- plugins = [gstomx]
 +
++plugins = [gstomx]
index 0000000,6af36c1..9c68127
mode 000000,100755..100644
--- /dev/null
@@@ -1,0 -1,71 +1,52 @@@
 -Version:        1.16.2
 -Release:        8
+ Name:           gst-omx
+ Summary:        GStreamer plug-in that allows communication with OpenMAX IL components
 -Source100:      common.tar.gz
 -Source1001:     gst-omx.manifest
++Version:        1.19.2
++Release:        0
+ License:        LGPL-2.1+
+ Group:          Multimedia/Framework
+ Source0:        %{name}-%{version}.tar.gz
 -%setup -q
 -%setup -q -T -D -a 100
 -cp %{SOURCE1001} .
+ BuildRequires:  which
++BuildRequires:  meson >= 0.48.0
+ BuildRequires:  pkgconfig(gstreamer-1.0)
+ BuildRequires:  pkgconfig(gstreamer-plugins-base-1.0)
+ BuildRequires:  pkgconfig(libtbm)
+ BuildRequires:  pkgconfig(mm-common)
+ %if "%{target}" == "rpi"
+ BuildRequires:  pkgconfig(bcm_host)
+ BuildRequires:  pkgconfig(brcmegl)
+ %endif
+ ExclusiveArch: %arm aarch64
+ %description
+ gst-openmax is a GStreamer plug-in that allows communication with OpenMAX IL components.
+ Multiple OpenMAX IL implementations can be used.
+ %prep
 -./autogen.sh --noconfigure
 -
 -export CFLAGS+=" -DTIZEN_FEATURE_OMX"
 -
++%setup -q -n %{name}-%{version}
+ %build
 -%configure \
 -      --disable-static \
 -      --prefix=/usr \
 -      --with-omx-target=rpi \
 -      --with-omx-header-path=/opt/vc/include/interface/vmcs_host/khronos/IL \
 -      sysconfdir=%{_hal_sysconfdir}
++export CFLAGS+=" -Wall -g -fPIC -DTIZEN_FEATURE_OMX"
++%meson --auto-features=auto --sysconfdir=%{_hal_sysconfdir}\
+ %if "%{target}" == "rpi"
 -%configure \
 -      --disable-static \
 -      --prefix=/usr \
 -      --with-omx-target=exynos64 \
 -      sysconfdir=%{_hal_sysconfdir}
++      -D target=rpi\
++      -D header_path=/opt/vc/include/interface/vmcs_host/khronos/IL
+ %else
+ %ifarch aarch64
 -%configure \
 -      --disable-static \
 -      --prefix=/usr \
 -      --with-omx-target=exynos \
 -      --enable-vp9 \
 -      sysconfdir=%{_hal_sysconfdir}
++      -D target=exynos64
+ %else
 -
 -make %{?jobs:-j%jobs}
 -
++      -D target=exynos\
++      -D vp9=true
+ %endif
+ %endif
 -%make_install
++%meson_build
+ %install
+ rm -rf %{buildroot}
 -%manifest gst-omx.manifest
++%meson_install
+ %files
++%manifest %{name}.manifest
+ %defattr(-,root,root,-)
+ %{_libdir}/gstreamer-1.0/libgstomx.so
+ %license COPYING