Release 1.2.0
authorJeon Hee Chul <heechul.jeon@samsung.com>
Wed, 2 Dec 2015 10:19:24 +0000 (19:19 +0900)
committerJeon Hee Chul <heechul.jeon@samsung.com>
Wed, 2 Dec 2015 10:21:09 +0000 (19:21 +0900)
Change-Id: I65b90a7d4caa26f56fe65a95fb086f8ac5d9e016

1  2 
configure.ac
omx/Makefile.am
omx/gstomx.c
omx/gstomx.h
omx/gstomxvideodec.c
omx/gstomxvideodec.h
omx/gstomxvideoenc.c

diff --cc configure.ac
index bfa1614,e87d240..3e79785
mode 100755,100644..100755
diff --cc omx/Makefile.am
@@@ -52,8 -68,8 +68,9 @@@ endi
  
  libgstomx_la_CFLAGS = \
        -DGST_USE_UNSTABLE_API=1 \
 +      $(CFLAGS) \
        $(OMX_INCLUDEPATH) \
+       $(GST_GL_CFLAGS) \
        $(GST_PLUGINS_BASE_CFLAGS) \
        $(GST_BASE_CFLAGS) \
        $(GST_CFLAGS) \
diff --cc omx/gstomx.c
index 66153b6,9a77e5b..628851b
mode 100755,100644..100755
diff --cc omx/gstomx.h
Simple merge
index d3f341f,8590301..2475ed2
mode 100755,100644..100755
  #include "config.h"
  #endif
  
 +//#define CODEC_DEC_OUTPUT_DUMP
  #include <gst/gst.h>
- #include <gst/video/gstvideometa.h>
- #include <gst/video/gstvideopool.h>
- #include <string.h>
- #if defined(CODEC_DEC_OUTPUT_DUMP)
- #include <stdio.h> /* for dump */
- #endif
- #include "gstomxvideodec.h"
- GST_DEBUG_CATEGORY_STATIC (gst_omx_video_dec_debug_category);
- #define GST_CAT_DEFAULT gst_omx_video_dec_debug_category
- typedef struct _GstOMXMemory GstOMXMemory;
- typedef struct _GstOMXMemoryAllocator GstOMXMemoryAllocator;
- typedef struct _GstOMXMemoryAllocatorClass GstOMXMemoryAllocatorClass;
- struct _GstOMXMemory
- {
-   GstMemory mem;
-   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);
- }
- static gpointer
- gst_omx_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
- {
-   GstOMXMemory *omem = (GstOMXMemory *) mem;
-   return omem->buf->omx_buf->pBuffer + omem->mem.offset;
- }
- static void
- gst_omx_memory_unmap (GstMemory * mem)
- {
- }
- static GstMemory *
- gst_omx_memory_share (GstMemory * mem, gssize offset, gssize size)
- {
-   g_assert_not_reached ();
-   return NULL;
- }
- 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);
- }
- static GstMemory *
- gst_omx_memory_allocator_alloc (GstAllocator * allocator, GstMemoryFlags flags,
-     GstOMXBuffer * buf)
- {
-   GstOMXMemory *mem;
-   /* 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;
-   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, buf->port->port_def.nBufferAlignment,
-       0, buf->omx_buf->nAllocLen);
-   mem->buf = buf;
-   return GST_MEMORY_CAST (mem);
- }
- /* Buffer pool for the buffers of an OpenMAX port.
-  *
-  * This pool is only used if we either passed buffers from another
-  * pool to the OMX port or provide the OMX buffers directly to other
-  * elements.
-  *
-  *
-  * A buffer is in the pool if it is currently owned by the port,
-  * i.e. after OMX_{Fill,Empty}ThisBuffer(). A buffer is outside
-  * the pool after it was taken from the port after it was handled
-  * by the port, i.e. {Empty,Fill}BufferDone.
-  *
-  * Buffers can be allocated by us (OMX_AllocateBuffer()) or allocated
-  * by someone else and (temporarily) passed to this pool
-  * (OMX_UseBuffer(), OMX_UseEGLImage()). In the latter case the pool of
-  * the buffer will be overriden, and restored in free_buffer(). Other
-  * buffers are just freed there.
-  *
-  * The pool always has a fixed number of minimum and maximum buffers
-  * and these are allocated while starting the pool and released afterwards.
-  * They correspond 1:1 to the OMX buffers of the port, which are allocated
-  * before the pool is started.
-  *
-  * Acquiring a buffer from this pool happens after the OMX buffer has
-  * been acquired from the port. gst_buffer_pool_acquire_buffer() is
-  * supposed to return the buffer that corresponds to the OMX buffer.
-  *
-  * For buffers provided to upstream, the buffer will be passed to
-  * the component manually when it arrives and then unreffed. If the
-  * buffer is released before reaching the component it will be just put
-  * back into the pool as if EmptyBufferDone has happened. If it was
-  * passed to the component, it will be back into the pool when it was
-  * released and EmptyBufferDone has happened.
-  *
-  * For buffers provided to downstream, the buffer will be returned
-  * back to the component (OMX_FillThisBuffer()) when it is released.
-  */
- static GQuark gst_omx_buffer_data_quark = 0;
- #define GST_OMX_BUFFER_POOL(pool) ((GstOMXBufferPool *) pool)
- typedef struct _GstOMXBufferPool GstOMXBufferPool;
- typedef struct _GstOMXBufferPoolClass GstOMXBufferPoolClass;
- struct _GstOMXBufferPool
- {
-   GstVideoBufferPool parent;
-   GstElement *element;
-   GstCaps *caps;
-   gboolean add_videometa;
-   GstVideoInfo video_info;
-   /* Owned by element, element has to stop this pool before
-    * it destroys component or port */
-   GstOMXComponent *component;
-   GstOMXPort *port;
-   GstAllocator *allocator;
-   /* Set from outside this pool */
-   /* TRUE if we're currently allocating all our buffers */
-   gboolean allocating;
-   /* TRUE if the pool is not used anymore */
-   gboolean deactivated;
-   /* For populating the pool from another one */
-   GstBufferPool *other_pool;
-   GPtrArray *buffers;
-   /* Used during acquire for output ports to
-    * specify which buffer has to be retrieved
-    * and during alloc, which buffer has to be
-    * wrapped
-    */
-   gint current_buffer_index;
- };
- struct _GstOMXBufferPoolClass
- {
-   GstVideoBufferPoolClass parent_class;
- };
- GType gst_omx_buffer_pool_get_type (void);
- G_DEFINE_TYPE (GstOMXBufferPool, gst_omx_buffer_pool, GST_TYPE_BUFFER_POOL);
- static gboolean
- gst_omx_buffer_pool_start (GstBufferPool * bpool)
- {
-   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-   /* Only allow to start the pool if we still are attached
-    * to a component and port */
-   GST_OBJECT_LOCK (pool);
-   if (!pool->component || !pool->port) {
-     GST_OBJECT_UNLOCK (pool);
-     return FALSE;
-   }
-   GST_OBJECT_UNLOCK (pool);
-   return
-       GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->start (bpool);
- }
- static gboolean
- gst_omx_buffer_pool_stop (GstBufferPool * bpool)
- {
-   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-   /* Remove any buffers that are there */
-   if(pool->buffers)
-       g_ptr_array_set_size (pool->buffers, 0);
-   if (pool->caps)
-     gst_caps_unref (pool->caps);
-   pool->caps = NULL;
-   pool->add_videometa = FALSE;
-   return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->stop (bpool);
- }
- static const gchar **
- gst_omx_buffer_pool_get_options (GstBufferPool * bpool)
- {
-   static const gchar *raw_video_options[] =
-       { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL };
-   static const gchar *options[] = { NULL };
-   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-   GST_OBJECT_LOCK (pool);
-   if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo
-       && pool->port->port_def.format.video.eCompressionFormat ==
-       OMX_VIDEO_CodingUnused) {
-     GST_OBJECT_UNLOCK (pool);
-     return raw_video_options;
-   }
-   GST_OBJECT_UNLOCK (pool);
-   return options;
- }
- static gboolean
- gst_omx_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
- {
-   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-   GstCaps *caps;
-   GST_OBJECT_LOCK (pool);
-   if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
-     goto wrong_config;
-   if (caps == NULL)
-     goto no_caps;
-   if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo
-       && pool->port->port_def.format.video.eCompressionFormat ==
-       OMX_VIDEO_CodingUnused) {
-     GstVideoInfo info;
-     /* now parse the caps from the config */
-     if (!gst_video_info_from_caps (&info, caps))
-       goto wrong_video_caps;
-     /* enable metadata based on config of the pool */
-     pool->add_videometa =
-         gst_buffer_pool_config_has_option (config,
-         GST_BUFFER_POOL_OPTION_VIDEO_META);
-     pool->video_info = info;
-   }
-   if (pool->caps)
-     gst_caps_unref (pool->caps);
-   pool->caps = gst_caps_ref (caps);
-   GST_OBJECT_UNLOCK (pool);
-   return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->set_config
-       (bpool, config);
-   /* ERRORS */
- wrong_config:
-   {
-     GST_OBJECT_UNLOCK (pool);
-     GST_WARNING_OBJECT (pool, "invalid config");
-     return FALSE;
-   }
- no_caps:
-   {
-     GST_OBJECT_UNLOCK (pool);
-     GST_WARNING_OBJECT (pool, "no caps in config");
-     return FALSE;
-   }
- wrong_video_caps:
-   {
-     GST_OBJECT_UNLOCK (pool);
-     GST_WARNING_OBJECT (pool,
-         "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
-     return FALSE;
-   }
- }
- static GstFlowReturn
- gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
-     GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
- {
-   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-   GstBuffer *buf;
-   GstOMXBuffer *omx_buf;
-   g_return_val_if_fail (pool->allocating, GST_FLOW_ERROR);
-   omx_buf = g_ptr_array_index (pool->port->buffers, pool->current_buffer_index);
-   g_return_val_if_fail (omx_buf != NULL, GST_FLOW_ERROR);
-   if (pool->other_pool) {
-     guint i, n;
-     buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
-     g_assert (pool->other_pool == buf->pool);
-     gst_object_replace ((GstObject **) & buf->pool, NULL);
-     n = gst_buffer_n_memory (buf);
-     for (i = 0; i < n; i++) {
-       GstMemory *mem = gst_buffer_peek_memory (buf, i);
-       /* 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
-        */
-       GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_NO_SHARE);
-     }
-     if (pool->add_videometa) {
-       GstVideoMeta *meta;
-       meta = gst_buffer_get_video_meta (buf);
-       if (!meta) {
-         gst_buffer_add_video_meta (buf, GST_VIDEO_FRAME_FLAG_NONE,
-             GST_VIDEO_INFO_FORMAT (&pool->video_info),
-             GST_VIDEO_INFO_WIDTH (&pool->video_info),
-             GST_VIDEO_INFO_HEIGHT (&pool->video_info));
-       }
-     }
-   } else {
-     GstMemory *mem;
-     mem = gst_omx_memory_allocator_alloc (pool->allocator, 0, omx_buf);
-     buf = gst_buffer_new ();
-     gst_buffer_append_memory (buf, mem);
-     g_ptr_array_add (pool->buffers, buf);
-     if (pool->add_videometa) {
-       gsize offset[4] = { 0, };
-       gint stride[4] = { 0, };
-       switch (pool->video_info.finfo->format) {
-         case GST_VIDEO_FORMAT_I420:
-           offset[0] = 0;
-           stride[0] = pool->port->port_def.format.video.nStride;
-           offset[1] =
-               stride[0] * pool->port->port_def.format.video.nSliceHeight;
-           stride[1] = pool->port->port_def.format.video.nStride / 2;
-           offset[2] =
-               offset[1] +
-               stride[1] * (pool->port->port_def.format.video.nSliceHeight / 2);
-           stride[2] = pool->port->port_def.format.video.nStride / 2;
-           break;
-         case GST_VIDEO_FORMAT_NV12:
-         case GST_VIDEO_FORMAT_SN12:
-         case GST_VIDEO_FORMAT_ST12:
-           offset[0] = 0;
-           stride[0] = pool->port->port_def.format.video.nStride;
-           offset[1] =
-               stride[0] * pool->port->port_def.format.video.nSliceHeight;
-           stride[1] = pool->port->port_def.format.video.nStride;
-           break;
-         default:
-           g_assert_not_reached ();
-           break;
-       }
-       gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
-           GST_VIDEO_INFO_FORMAT (&pool->video_info),
-           GST_VIDEO_INFO_WIDTH (&pool->video_info),
-           GST_VIDEO_INFO_HEIGHT (&pool->video_info),
-           GST_VIDEO_INFO_N_PLANES (&pool->video_info), offset, stride);
-     }
-   }
-   gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf),
-       gst_omx_buffer_data_quark, omx_buf, NULL);
  
-   *buffer = buf;
-   pool->current_buffer_index++;
-   return GST_FLOW_OK;
- }
- static void
- gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
- {
-   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-   /* If the buffers belong to another pool, restore them now */
-   GST_OBJECT_LOCK (pool);
-   if (pool->other_pool) {
-     gst_object_replace ((GstObject **) & buffer->pool,
-         (GstObject *) pool->other_pool);
-   }
-   GST_OBJECT_UNLOCK (pool);
-   gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer),
-       gst_omx_buffer_data_quark, NULL, NULL);
-   GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->free_buffer (bpool,
-       buffer);
- }
- static GstFlowReturn
- gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool,
-     GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
- {
-   GstFlowReturn ret;
-   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-   if (pool->port->port_def.eDir == OMX_DirOutput) {
-     GstBuffer *buf;
-     g_return_val_if_fail (pool->current_buffer_index != -1, GST_FLOW_ERROR);
-     buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
-     g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
-     *buffer = buf;
-     ret = GST_FLOW_OK;
-     /* If it's our own memory we have to set the sizes */
-     if (!pool->other_pool) {
-       GstMemory *mem = gst_buffer_peek_memory (*buffer, 0);
-       g_assert (mem
-           && g_strcmp0 (mem->allocator->mem_type, GST_OMX_MEMORY_TYPE) == 0);
-       mem->size = ((GstOMXMemory *) mem)->buf->omx_buf->nFilledLen;
-       mem->offset = ((GstOMXMemory *) mem)->buf->omx_buf->nOffset;
-     }
-   } else {
-     /* Acquire any buffer that is available to be filled by upstream */
-     ret =
-         GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->acquire_buffer
-         (bpool, buffer, params);
-   }
-   return ret;
- }
- static void
- gst_omx_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
- {
-   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-   OMX_ERRORTYPE err;
-   GstOMXBuffer *omx_buf;
-   g_assert (pool->component && pool->port);
-   if (!pool->allocating && !pool->deactivated) {
-     omx_buf =
-         gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer),
-         gst_omx_buffer_data_quark);
-     if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used) {
-       /* Release back to the port, can be filled again */
-       err = gst_omx_port_release_buffer (pool->port, omx_buf);
-       if (err != OMX_ErrorNone) {
-         GST_ELEMENT_ERROR (pool->element, LIBRARY, SETTINGS, (NULL),
-             ("Failed to relase output buffer to component: %s (0x%08x)",
-                 gst_omx_error_to_string (err), err));
-       }
-     } else if (!omx_buf->used) {
-       /* TODO: Implement.
-        *
-        * If not used (i.e. was not passed to the component) this should do
-        * the same as EmptyBufferDone.
-        * If it is used (i.e. was passed to the component) this should do
-        * nothing until EmptyBufferDone.
-        *
-        * EmptyBufferDone should release the buffer to the pool so it can
-        * be allocated again
-        *
-        * Needs something to call back here in EmptyBufferDone, like keeping
-        * a ref on the buffer in GstOMXBuffer until EmptyBufferDone... which
-        * would ensure that the buffer is always unused when this is called.
-        */
-       g_assert_not_reached ();
-       GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer
-           (bpool, buffer);
-     }
-   }
- }
- static void
- gst_omx_buffer_pool_finalize (GObject * object)
- {
-   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (object);
-   if (pool->element)
-     gst_object_unref (pool->element);
-   pool->element = NULL;
-   if (pool->buffers)
-     g_ptr_array_unref (pool->buffers);
-   pool->buffers = NULL;
-   if (pool->other_pool)
-     gst_object_unref (pool->other_pool);
-   pool->other_pool = NULL;
-   if (pool->allocator)
-     gst_object_unref (pool->allocator);
-   pool->allocator = NULL;
-   if (pool->caps)
-     gst_caps_unref (pool->caps);
-   pool->caps = NULL;
-   G_OBJECT_CLASS (gst_omx_buffer_pool_parent_class)->finalize (object);
- }
- static void
- gst_omx_buffer_pool_class_init (GstOMXBufferPoolClass * klass)
- {
-   GObjectClass *gobject_class = (GObjectClass *) klass;
-   GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
-   gst_omx_buffer_data_quark = g_quark_from_static_string ("GstOMXBufferData");
-   gobject_class->finalize = gst_omx_buffer_pool_finalize;
-   gstbufferpool_class->start = gst_omx_buffer_pool_start;
-   gstbufferpool_class->stop = gst_omx_buffer_pool_stop;
-   gstbufferpool_class->get_options = gst_omx_buffer_pool_get_options;
-   gstbufferpool_class->set_config = gst_omx_buffer_pool_set_config;
-   gstbufferpool_class->alloc_buffer = gst_omx_buffer_pool_alloc_buffer;
-   gstbufferpool_class->free_buffer = gst_omx_buffer_pool_free_buffer;
-   gstbufferpool_class->acquire_buffer = gst_omx_buffer_pool_acquire_buffer;
-   gstbufferpool_class->release_buffer = gst_omx_buffer_pool_release_buffer;
- }
+ #if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__)
+ #ifndef __VCCOREVER__
+ #define __VCCOREVER__ 0x04000000
+ #endif
  
- static void
- gst_omx_buffer_pool_init (GstOMXBufferPool * pool)
- {
-   pool->buffers = g_ptr_array_new ();
-   pool->allocator = g_object_new (gst_omx_memory_allocator_get_type (), NULL);
- }
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wredundant-decls"
+ #pragma GCC optimize ("gnu89-inline")
+ #endif
  
- static GstBufferPool *
- gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component,
-     GstOMXPort * port)
- {
-   GstOMXBufferPool *pool;
+ #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ #include <gst/gl/gl.h>
+ #include <gst/gl/egl/gsteglimagememory.h>
+ #endif
  
-   pool = g_object_new (gst_omx_buffer_pool_get_type (), NULL);
-   pool->element = gst_object_ref (element);
-   pool->component = component;
-   pool->port = port;
+ #if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__)
+ #pragma GCC reset_options
+ #pragma GCC diagnostic pop
+ #endif
  
-   return GST_BUFFER_POOL (pool);
- }
+ #include <string.h>
  
- typedef struct _BufferIdentification BufferIdentification;
- struct _BufferIdentification
- {
-   guint64 timestamp;
- };
+ #include "gstomxbufferpool.h"
+ #include "gstomxvideo.h"
+ #include "gstomxvideodec.h"
  
- static void
- buffer_identification_free (BufferIdentification * id)
- {
-   g_slice_free (BufferIdentification, id);
- }
+ GST_DEBUG_CATEGORY_STATIC (gst_omx_video_dec_debug_category);
+ #define GST_CAT_DEFAULT gst_omx_video_dec_debug_category
  
  /* prototypes */
  static void gst_omx_video_dec_finalize (GObject * object);
@@@ -786,17 -196,55 +202,64 @@@ gst_omx_video_dec_open (GstVideoDecode
    if (!self->dec_in_port || !self->dec_out_port)
      return FALSE;
  
 +#ifdef USE_TBM
 +
 +   self->hTBMBufMgr = tbm_bufmgr_init(self->drm_fd);
 +   if(self->hTBMBufMgr == NULL){
 +    GST_ERROR_OBJECT (self, "TBM initialization failed.");
 +    return FALSE;
 +   }
 +#endif
 +
    GST_DEBUG_OBJECT (self, "Opened decoder");
  
+ #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+   GST_DEBUG_OBJECT (self, "Opening EGL renderer");
+   self->egl_render =
+       gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
+       "OMX.broadcom.egl_render", NULL, klass->cdata.hacks);
+   if (!self->egl_render)
+     return FALSE;
+   if (gst_omx_component_get_state (self->egl_render,
+           GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
+     return FALSE;
+   {
+     OMX_PORT_PARAM_TYPE param;
+     OMX_ERRORTYPE err;
+     GST_OMX_INIT_STRUCT (&param);
+     err =
+         gst_omx_component_get_parameter (self->egl_render,
+         OMX_IndexParamVideoInit, &param);
+     if (err != OMX_ErrorNone) {
+       GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+           gst_omx_error_to_string (err), err);
+       /* Fallback */
+       in_port_index = 0;
+       out_port_index = 1;
+     } else {
+       GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u", param.nPorts,
+           param.nStartPortNumber);
+       in_port_index = param.nStartPortNumber + 0;
+       out_port_index = param.nStartPortNumber + 1;
+     }
+   }
+   self->egl_in_port =
+       gst_omx_component_add_port (self->egl_render, in_port_index);
+   self->egl_out_port =
+       gst_omx_component_add_port (self->egl_render, out_port_index);
+   if (!self->egl_in_port || !self->egl_out_port)
+     return FALSE;
+   GST_DEBUG_OBJECT (self, "Opened EGL renderer");
+ #endif
    return TRUE;
  }
  
@@@ -916,151 -389,25 +418,57 @@@ gst_omx_video_dec_change_state (GstElem
    if (ret == GST_STATE_CHANGE_FAILURE)
      return ret;
  
-   switch (transition) {
-     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-       break;
-     case GST_STATE_CHANGE_PAUSED_TO_READY:
-       self->downstream_flow_ret = GST_FLOW_FLUSHING;
-       self->started = FALSE;
-       if (!gst_omx_video_dec_shutdown (self))
-         ret = GST_STATE_CHANGE_FAILURE;
-       break;
-     case GST_STATE_CHANGE_READY_TO_NULL:
-       break;
-     default:
-       break;
-   }
-   return ret;
- }
- #define MAX_FRAME_DIST_TICKS  (5 * OMX_TICKS_PER_SECOND)
- #define MAX_FRAME_DIST_FRAMES (100)
- static GstVideoCodecFrame *
- _find_nearest_frame (GstOMXVideoDec * self, GstOMXBuffer * buf)
- {
-   GList *l, *best_l = NULL;
-   GList *finish_frames = NULL;
-   GstVideoCodecFrame *best = NULL;
-   guint64 best_timestamp = 0;
-   guint64 best_diff = G_MAXUINT64;
-   BufferIdentification *best_id = NULL;
-   GList *frames;
-   frames = gst_video_decoder_get_frames (GST_VIDEO_DECODER (self));
-   for (l = frames; l; l = l->next) {
-     GstVideoCodecFrame *tmp = l->data;
-     BufferIdentification *id = gst_video_codec_frame_get_user_data (tmp);
-     guint64 timestamp, diff;
-     /* This happens for frames that were just added but
-      * which were not passed to the component yet. Ignore
-      * them here!
-      */
-     if (!id)
-       continue;
-     timestamp = id->timestamp;
-     if (timestamp > buf->omx_buf->nTimeStamp)
-       diff = timestamp - buf->omx_buf->nTimeStamp;
-     else
-       diff = buf->omx_buf->nTimeStamp - timestamp;
-     if (best == NULL || diff < best_diff) {
-       best = tmp;
-       best_timestamp = timestamp;
-       best_diff = diff;
-       best_l = l;
-       best_id = id;
-       /* For frames without timestamp we simply take the first frame */
-       if ((buf->omx_buf->nTimeStamp == 0 && timestamp == 0) || diff == 0)
-         break;
-     }
-   }
-   if (best_id) {
-     for (l = frames; l && l != best_l; l = l->next) {
-       GstVideoCodecFrame *tmp = l->data;
-       BufferIdentification *id = gst_video_codec_frame_get_user_data (tmp);
-       guint64 diff_ticks, diff_frames;
-       /* This happens for frames that were just added but
-        * which were not passed to the component yet. Ignore
-        * them here!
-        */
-       if (!id)
-         continue;
-       if (id->timestamp > best_timestamp)
-         break;
-       if (id->timestamp == 0 || best_timestamp == 0)
-         diff_ticks = 0;
-       else
-         diff_ticks = best_timestamp - id->timestamp;
-       diff_frames = best->system_frame_number - tmp->system_frame_number;
-       if (diff_ticks > MAX_FRAME_DIST_TICKS
-           || diff_frames > MAX_FRAME_DIST_FRAMES) {
-         finish_frames =
-             g_list_prepend (finish_frames, gst_video_codec_frame_ref (tmp));
-       }
-     }
-   }
-   if (finish_frames) {
-     g_warning ("Too old frames, bug in decoder -- please file a bug");
-     for (l = finish_frames; l; l = l->next) {
-       gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), l->data);
-     }
-   }
-   if (best)
-     gst_video_codec_frame_ref (best);
+   switch (transition) {
+     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+       break;
+     case GST_STATE_CHANGE_PAUSED_TO_READY:
+       self->downstream_flow_ret = GST_FLOW_FLUSHING;
+       self->started = FALSE;
  
-   g_list_foreach (frames, (GFunc) gst_video_codec_frame_unref, NULL);
-   g_list_free (frames);
+       if (!gst_omx_video_dec_shutdown (self))
+         ret = GST_STATE_CHANGE_FAILURE;
+       break;
+     case GST_STATE_CHANGE_READY_TO_NULL:
+       break;
+     default:
+       break;
+   }
  
-   return best;
+   return ret;
  }
  
 +#ifdef CODEC_DEC_OUTPUT_DUMP /* for decoder output dump */
 +static inline void
 +decoder_output_dump(GstOMXVideoDec *self, MMVideoBuffer *outbuf)
 +{
 +  char *temp = (char *)outbuf->data[0];
 +  int i = 0;
 +  char filename[100]={0};
 +  FILE *fp = NULL;
 +  int ret =0;
 +
 +  GST_ERROR_OBJECT (self, "codec dec output dump start. w = %d, h = %d", outbuf->width[0], outbuf->height[0]);
 +
 +  sprintf(filename, "/opt/usr/dec_output_dump_%d_%d.yuv", outbuf->stride_width[0], outbuf->height[0]);
 +  fp = fopen(filename, "ab");
 +
 +  for (i = 0; i < outbuf->height[0]; i++) {
 +    ret = fwrite(temp, outbuf->width[0], 1, fp);
 +    temp += outbuf->stride_width[0];
 +  }
 +
 +  temp = (char *)outbuf->data[1];
 +
 +  for(i = 0; i < outbuf->height[1]; i++) {
 +   ret = fwrite(temp, outbuf->width[1], 1, fp);
 +    temp += outbuf->stride_width[1];
 +  }
 +
 +  GST_ERROR_OBJECT (self,"codec dec output dumped!! ret = %d", ret);
 +  fclose(fp);
 +}
 +#endif
 +
  static gboolean
  gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
      GstOMXBuffer * inbuf, GstBuffer * outbuf)
      ret = TRUE;
      goto done;
    }
 +#endif  //ENS:a
  
    /* Different strides */
-   switch (vinfo->finfo->format) {
-     case GST_VIDEO_FORMAT_I420:{
-       gint i, j, height, width;
-       guint8 *src, *dest;
-       gint src_stride, dest_stride;
-       gst_video_frame_map (&frame, vinfo, outbuf, GST_MAP_WRITE);
-       for (i = 0; i < 3; i++) {
-         if (i == 0) {
-           src_stride = port_def->format.video.nStride;
-           dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i);
-           /* XXX: Try this if no stride was set */
-           if (src_stride == 0)
-             src_stride = dest_stride;
-         } else {
-           src_stride = port_def->format.video.nStride / 2;
-           dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i);
-           /* XXX: Try this if no stride was set */
-           if (src_stride == 0)
-             src_stride = dest_stride;
-         }
-         src = inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset;
-         if (i > 0)
-           src +=
-               port_def->format.video.nSliceHeight *
-               port_def->format.video.nStride;
-         if (i == 2)
-           src +=
-               (port_def->format.video.nSliceHeight / 2) *
-               (port_def->format.video.nStride / 2);
-         dest = GST_VIDEO_FRAME_COMP_DATA (&frame, i);
-         height = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, i);
-         width = GST_VIDEO_FRAME_COMP_WIDTH (&frame, i);
-         for (j = 0; j < height; j++) {
-           memcpy (dest, src, width);
-           src += src_stride;
-           dest += dest_stride;
-         }
-       }
-       gst_video_frame_unmap (&frame);
-       ret = TRUE;
-       break;
+   if (gst_video_frame_map (&frame, vinfo, outbuf, GST_MAP_WRITE)) {
+     const guint nstride = port_def->format.video.nStride;
+     const guint nslice = port_def->format.video.nSliceHeight;
+     guint src_stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
+     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, };
+     const guint8 *src;
+     guint p;
+     switch (GST_VIDEO_INFO_FORMAT (vinfo)) {
+       case GST_VIDEO_FORMAT_ABGR:
+       case GST_VIDEO_FORMAT_ARGB:
+         dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 4;
+         break;
+       case GST_VIDEO_FORMAT_RGB16:
+       case GST_VIDEO_FORMAT_BGR16:
+       case GST_VIDEO_FORMAT_YUY2:
+       case GST_VIDEO_FORMAT_UYVY:
+       case GST_VIDEO_FORMAT_YVYU:
+         dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 2;
+         break;
+       case GST_VIDEO_FORMAT_GRAY8:
+         dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+         break;
+       case GST_VIDEO_FORMAT_I420:
+         dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+         src_stride[1] = nstride / 2;
+         src_size[1] = (src_stride[1] * nslice) / 2;
+         dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
+         dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
+         src_stride[2] = nstride / 2;
+         src_size[2] = (src_stride[1] * nslice) / 2;
+         dst_width[2] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
+         dst_height[2] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
+         break;
+       case GST_VIDEO_FORMAT_NV12:
+         dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+         src_stride[1] = nstride;
+         src_size[1] = src_stride[1] * nslice / 2;
+         dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
+         dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
+         break;
+       case GST_VIDEO_FORMAT_NV16:
+         dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+         src_stride[1] = nstride;
+         src_size[1] = src_stride[1] * nslice;
+         dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
+         dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo);
+         break;
+       default:
+         g_assert_not_reached ();
+         break;
      }
-     case GST_VIDEO_FORMAT_NV12:{
-       gint i, j, height, width;
-       guint8 *src, *dest;
-       gint src_stride, dest_stride;
-       gst_video_frame_map (&frame, vinfo, outbuf, GST_MAP_WRITE);
-       for (i = 0; i < 2; i++) {
-         if (i == 0) {
-           src_stride = port_def->format.video.nStride;
-           dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i);
-           /* XXX: Try this if no stride was set */
-           if (src_stride == 0)
-             src_stride = dest_stride;
-         } else {
-           src_stride = port_def->format.video.nStride;
-           dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i);
-           /* XXX: Try this if no stride was set */
-           if (src_stride == 0)
-             src_stride = dest_stride;
-         }
-         src = inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset;
-         if (i == 1)
-           src +=
-               port_def->format.video.nSliceHeight *
-               port_def->format.video.nStride;
-         dest = GST_VIDEO_FRAME_COMP_DATA (&frame, i);
-         height = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, i);
-         width = GST_VIDEO_FRAME_COMP_WIDTH (&frame, i) * (i == 0 ? 1 : 2);
  
-         for (j = 0; j < height; j++) {
-           memcpy (dest, src, width);
-           src += src_stride;
-           dest += dest_stride;
-         }
+     src = inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset;
+     for (p = 0; p < GST_VIDEO_INFO_N_PLANES (vinfo); p++) {
+       const guint8 *data;
+       guint8 *dst;
+       guint h;
+       dst = GST_VIDEO_FRAME_PLANE_DATA (&frame, p);
+       data = src;
+       for (h = 0; h < dst_height[p]; h++) {
+         memcpy (dst, data, dst_width[p]);
+         dst += GST_VIDEO_INFO_PLANE_STRIDE (vinfo, p);
+         data += src_stride[p];
        }
-       gst_video_frame_unmap (&frame);
-       ret = TRUE;
-       break;
-     }
-     case GST_VIDEO_FORMAT_SN12:
-     case GST_VIDEO_FORMAT_ST12:{
-         GstMemory *mem_imgb = NULL;
-         void *imgb_data = NULL;
- #ifdef USE_MM_VIDEO_BUFFER
-         MMVideoBuffer *out_imgb = NULL;
-         out_imgb = (MMVideoBuffer*)(inbuf->omx_buf->pBuffer);
-         out_imgb->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
-         if (out_imgb->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
-           GST_LOG_OBJECT (self, "dec output buf: fd[0]:%d  fd[1]:%d fd[2]:%d  w[0]:%d h[0]:%d  buf_share_method:%d",
-                   out_imgb->handle.dmabuf_fd[0], out_imgb->handle.dmabuf_fd[1], out_imgb->handle.dmabuf_fd[2],
-                   out_imgb->width[0], out_imgb->height[0], out_imgb->type);
-         } else if (out_imgb->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
-           GST_LOG_OBJECT (self, "dec output uses hw addr");
-         } else {
-           GST_WARNING_OBJECT (self, "dec output buf has TBM_BO buf_share_method");
-         }
- #ifdef CODEC_DEC_OUTPUT_DUMP
-       decoder_output_dump(self, out_imgb);
- #endif
- #else
-         SCMN_IMGB *out_imgb = NULL;
-         out_imgb = (SCMN_IMGB*)(inbuf->omx_buf->pBuffer);
-         if (out_imgb->buf_share_method == BUF_SHARE_METHOD_FD) {
-           GST_LOG_OBJECT (self, "dec output buf: fd[0]:%d  fd[1]:%d fd[2]:%d  w[0]:%d h[0]:%d  buf_share_method:%d",
-                   out_imgb->fd[0], out_imgb->fd[1], out_imgb->fd[2], out_imgb->w[0], out_imgb->h[0], out_imgb->buf_share_method);
-         } else if (out_imgb->buf_share_method == BUF_SHARE_METHOD_PADDR) {
-           GST_LOG_OBJECT (self, "dec output uses hw addr");
-         } else {
-           GST_WARNING_OBJECT (self, "dec output buf has wrong buf_share_method");
-         }
- #endif
-         if (gst_buffer_n_memory(outbuf) < 2) {
-             imgb_data = g_malloc0(sizeof(*out_imgb));
-             mem_imgb = gst_memory_new_wrapped(0, imgb_data, sizeof(*out_imgb), 0, sizeof(*out_imgb), imgb_data, g_free);
-             gst_buffer_append_memory(outbuf, mem_imgb);
-         } else {
-             GstMapInfo imgb_info = GST_MAP_INFO_INIT;
-             mem_imgb = gst_buffer_peek_memory(outbuf, 1);
-             gst_memory_map(mem_imgb, &imgb_info, GST_MAP_WRITE);
-             imgb_data = imgb_info.data;
-             gst_memory_unmap(mem_imgb, &imgb_info);
-         }
- #ifdef USE_MM_VIDEO_BUFFER
-         memcpy(imgb_data, out_imgb, sizeof(MMVideoBuffer));
- #else
-         memcpy(imgb_data, out_imgb, sizeof(SCMN_IMGB));
- #endif
-         ret = TRUE;
-         break;
+       src += src_size[p];
      }
-     default:
-       GST_ERROR_OBJECT (self, "Unsupported format");
-       goto done;
-       break;
-   }
  
+     gst_video_frame_unmap (&frame);
+     ret = TRUE;
+   } else {
+     GST_ERROR_OBJECT (self, "Can't map output buffer to frame");
+     goto done;
+   }
  
  done:
    if (ret) {
@@@ -1316,14 -611,150 +674,151 @@@ gst_omx_video_dec_allocate_output_buffe
      GST_DEBUG_OBJECT (self, "No pool available, not negotiated yet");
    }
  
-   min = max = port->port_def.nBufferCountMin;
-   if (caps){
-     GST_LOG_OBJECT(self,"gst-omx: Creating our own outport buffer pool. min:[%d], max:[%d]",min,max);
+ #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+   /* Will retry without EGLImage */
+   if (self->eglimage && !eglimage) {
+     GST_DEBUG_OBJECT (self,
+         "Wanted to use EGLImage but downstream doesn't support it");
+     err = OMX_ErrorUndefined;
+     goto done;
+   }
+ #endif
+   if (caps)
      self->out_port_pool =
          gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->dec, port);
 +  }
  
-   /* TODO: Implement EGLImage handling and usage of other downstream buffers */
+ #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+   if (eglimage) {
+     GList *buffers = NULL;
+     GList *images = NULL;
+     gint i;
+     GstBufferPoolAcquireParams params = { 0, };
+     EGLDisplay egl_display = EGL_NO_DISPLAY;
+     GST_DEBUG_OBJECT (self, "Trying to allocate %d EGLImages", min);
+     for (i = 0; i < min; i++) {
+       GstBuffer *buffer;
+       GstMemory *mem;
+       if (gst_buffer_pool_acquire_buffer (pool, &buffer, &params) != GST_FLOW_OK
+           || gst_buffer_n_memory (buffer) != 1
+           || !(mem = gst_buffer_peek_memory (buffer, 0))
+           || g_strcmp0 (mem->allocator->mem_type,
+               GST_EGL_IMAGE_MEMORY_TYPE) != 0) {
+         GST_INFO_OBJECT (self, "Failed to allocated %d-th EGLImage", i);
+         g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+         g_list_free (images);
+         buffers = NULL;
+         images = NULL;
+         /* TODO: For non-RPi targets we want to use the normal memory code below */
+         /* Retry without EGLImage */
+         err = OMX_ErrorUndefined;
+         goto done;
+       }
+       buffers = g_list_append (buffers, buffer);
+       gst_egl_image_memory_set_orientation (mem,
+           GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_FLIP);
+       images = g_list_append (images, gst_egl_image_memory_get_image (mem));
+       if (egl_display == EGL_NO_DISPLAY)
+         egl_display = gst_egl_image_memory_get_display (mem);
+     }
+     GST_DEBUG_OBJECT (self, "Allocated %d EGLImages successfully", min);
+     /* Everything went fine? */
+     if (eglimage) {
+       GST_DEBUG_OBJECT (self, "Setting EGLDisplay");
+       self->egl_out_port->port_def.format.video.pNativeWindow = egl_display;
+       err =
+           gst_omx_port_update_port_definition (self->egl_out_port,
+           &self->egl_out_port->port_def);
+       if (err != OMX_ErrorNone) {
+         GST_INFO_OBJECT (self,
+             "Failed to set EGLDisplay on port: %s (0x%08x)",
+             gst_omx_error_to_string (err), err);
+         g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+         g_list_free (images);
+         /* TODO: For non-RPi targets we want to use the normal memory code below */
+         /* Retry without EGLImage */
+         goto done;
+       } else {
+         GList *l;
+         if (min != port->port_def.nBufferCountActual) {
+           err = gst_omx_port_update_port_definition (port, NULL);
+           if (err == OMX_ErrorNone) {
+             port->port_def.nBufferCountActual = min;
+             err = gst_omx_port_update_port_definition (port, &port->port_def);
+           }
+           if (err != OMX_ErrorNone) {
+             GST_INFO_OBJECT (self,
+                 "Failed to configure %u output buffers: %s (0x%08x)", min,
+                 gst_omx_error_to_string (err), err);
+             g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+             g_list_free (images);
+             /* TODO: For non-RPi targets we want to use the normal memory code below */
+             /* Retry without EGLImage */
+             goto done;
+           }
+         }
+         if (!gst_omx_port_is_enabled (port)) {
+           err = gst_omx_port_set_enabled (port, TRUE);
+           if (err != OMX_ErrorNone) {
+             GST_INFO_OBJECT (self,
+                 "Failed to enable port: %s (0x%08x)",
+                 gst_omx_error_to_string (err), err);
+             g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+             g_list_free (images);
+             /* TODO: For non-RPi targets we want to use the normal memory code below */
+             /* Retry without EGLImage */
+             goto done;
+           }
+         }
+         err = gst_omx_port_use_eglimages (port, images);
+         g_list_free (images);
+         if (err != OMX_ErrorNone) {
+           GST_INFO_OBJECT (self,
+               "Failed to pass EGLImages to port: %s (0x%08x)",
+               gst_omx_error_to_string (err), err);
+           g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+           /* TODO: For non-RPi targets we want to use the normal memory code below */
+           /* Retry without EGLImage */
+           goto done;
+         }
+         err = gst_omx_port_wait_enabled (port, 2 * GST_SECOND);
+         if (err != OMX_ErrorNone) {
+           GST_INFO_OBJECT (self,
+               "Failed to wait until port is enabled: %s (0x%08x)",
+               gst_omx_error_to_string (err), err);
+           g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+           /* TODO: For non-RPi targets we want to use the normal memory code below */
+           /* Retry without EGLImage */
+           goto done;
+         }
+         GST_DEBUG_OBJECT (self, "Populating internal buffer pool");
+         GST_OMX_BUFFER_POOL (self->out_port_pool)->other_pool =
+             GST_BUFFER_POOL (gst_object_ref (pool));
+         for (l = buffers; l; l = l->next) {
+           g_ptr_array_add (GST_OMX_BUFFER_POOL (self->out_port_pool)->buffers,
+               l->data);
+         }
+         g_list_free (buffers);
+         /* All good and done, set caps below */
+       }
+     }
+   }
+ #endif
  
    /* If not using EGLImage or trying to use EGLImage failed */
    if (!eglimage) {
@@@ -2283,13 -1977,19 +2069,23 @@@ gst_omx_video_dec_set_format (GstVideoD
    if (needs_disable) {
      if (gst_omx_port_set_enabled (self->dec_in_port, TRUE) != OMX_ErrorNone)
        return FALSE;
 +#ifdef USE_TBM
 +    if(gst_omx_port_tbm_allocate_dec_buffers(self->hTBMBufMgr,self->dec_in_port, 0) != OMX_ErrorNone)
 +     return FALSE;
 +#else
      if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
        return FALSE;
- #endif
+     if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+       if (gst_omx_port_set_enabled (self->dec_out_port, TRUE) != OMX_ErrorNone)
+         return FALSE;
+       if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
+         return FALSE;
+       if (gst_omx_port_wait_enabled (self->dec_out_port,
+               5 * GST_SECOND) != OMX_ErrorNone)
+         return FALSE;
+     }
  
      if (gst_omx_port_wait_enabled (self->dec_in_port,
              5 * GST_SECOND) != OMX_ErrorNone)
Simple merge
index 82941fc,0f64a02..cd6be10
mode 100755,100644..100755
  #include <gst/video/gstvideometa.h>
  #include <string.h>
  
+ #include "gstomxvideo.h"
  #include "gstomxvideoenc.h"
  
 +//#define CODEC_ENC_INPUT_DUMP
  GST_DEBUG_CATEGORY_STATIC (gst_omx_video_enc_debug_category);
  #define GST_CAT_DEFAULT gst_omx_video_enc_debug_category
  
@@@ -1323,14 -1092,20 +1151,25 @@@ gst_omx_video_enc_set_format (GstVideoE
    if (needs_disable) {
      if (gst_omx_port_set_enabled (self->enc_in_port, TRUE) != OMX_ErrorNone)
        return FALSE;
 +#ifdef USE_TBM
 +    if(gst_omx_port_tbm_allocate_enc_buffers(self->hTBMBufMgr,self->enc_in_port,
 +        self->enc_in_port->port_def.format.video.eCompressionFormat) != OMX_ErrorNone)
 +        return FALSE;
 +#else
      if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
        return FALSE;
- #endif
+     if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+       if (gst_omx_port_set_enabled (self->enc_out_port, TRUE) != OMX_ErrorNone)
+         return FALSE;
+       if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+         return FALSE;
+       if (gst_omx_port_wait_enabled (self->enc_out_port,
+               5 * GST_SECOND) != OMX_ErrorNone)
+         return FALSE;
+     }
      if (gst_omx_port_wait_enabled (self->enc_in_port,
              5 * GST_SECOND) != OMX_ErrorNone)
        return FALSE;