summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/gstducati.c16
-rw-r--r--src/gstducati.h2
-rw-r--r--src/gstducatibufferpool.c239
-rw-r--r--src/gstducatibufferpool.h73
-rw-r--r--src/gstducatividdec.c35
-rw-r--r--src/gstducatividdec.h3
7 files changed, 357 insertions, 13 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6224927..f3d69f3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,7 @@ noinst_HEADERS = \
gstducatimpeg4dec.h \
gstducatih264dec.h \
gstducatividdec.h \
+ gstducatibufferpool.h \
gstducati.h
# sources used to compile this plug-in
@@ -20,6 +21,7 @@ libgstducati_la_SOURCES = \
gstducatimpeg4dec.c \
gstducatih264dec.c \
gstducatividdec.c \
+ gstducatibufferpool.c \
gstducati.c \
$(noinst_HEADERS)
diff --git a/src/gstducati.c b/src/gstducati.c
index 1fcbaa7..d805911 100644
--- a/src/gstducati.c
+++ b/src/gstducati.c
@@ -23,6 +23,7 @@
#include <gst/gst.h>
+#include "gstducati.h"
#include "gstducatih264dec.h"
#include "gstducatimpeg4dec.h"
#include "gstducatimpeg2dec.h"
@@ -59,22 +60,27 @@ gst_ducati_alloc_1d (gint sz)
}
void *
-gst_ducati_alloc_2d (gint width, gint height)
+gst_ducati_alloc_2d (gint width, gint height, guint * sz)
{
MemAllocBlock block[] = { {
.pixelFormat = PIXEL_FMT_8BIT,
.dim = {.area = {
.width = width,
- .height = height,
- }}
+ .height = ALIGN2 (height, 1),
+ }},
+ .stride = 4096
}, {
.pixelFormat = PIXEL_FMT_16BIT,
.dim = {.area = {
.width = width,
- .height = height / 2,
- }}
+ .height = ALIGN2 (height, 1) / 2,
+ }},
+ .stride = 4096
}
};
+ if (sz) {
+ *sz = (4096 * ALIGN2 (height, 1) * 3) / 2;
+ }
return MemMgr_Alloc (block, 2);
}
diff --git a/src/gstducati.h b/src/gstducati.h
index 60cee7e..3d50313 100644
--- a/src/gstducati.h
+++ b/src/gstducati.h
@@ -42,7 +42,7 @@ GST_DEBUG_CATEGORY_EXTERN (gst_ducati_debug);
#define ALIGN2(x,n) (((x) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1))
void * gst_ducati_alloc_1d (gint sz);
-void * gst_ducati_alloc_2d (gint width, gint height);
+void * gst_ducati_alloc_2d (gint width, gint height, guint * sz);
XDAS_Int16 gst_ducati_get_mem_type (SSPtr paddr);
G_END_DECLS
diff --git a/src/gstducatibufferpool.c b/src/gstducatibufferpool.c
new file mode 100644
index 0000000..6be3727
--- /dev/null
+++ b/src/gstducatibufferpool.c
@@ -0,0 +1,239 @@
+/*
+ * GStreamer
+ * Copyright (c) 2010, Texas Instruments Incorporated
+ *
+ * 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
+ */
+
+#include "gstducatibufferpool.h"
+
+/*
+ * GstDucatiBuffer
+ */
+
+static GstBufferClass *buffer_parent_class;
+
+/* Get the original buffer, or whatever is the best output buffer.
+ * Consumes the input reference, produces the output reference
+ */
+GstBuffer *
+gst_ducati_buffer_get (GstDucatiBuffer * self)
+{
+ if (self->orig) {
+ // TODO copy to orig buffer.. if needed.
+ gst_buffer_unref (self->orig);
+ self->orig = NULL;
+ }
+ return GST_BUFFER (self);
+}
+
+static GstDucatiBuffer *
+gst_ducati_buffer_new (GstDucatiBufferPool * pool)
+{
+ GstDucatiBuffer *self = (GstDucatiBuffer *)
+ gst_mini_object_new (GST_TYPE_DUCATIBUFFER);
+ guint sz;
+
+ GST_LOG_OBJECT (pool->element, "creating buffer %p in pool %p", self, pool);
+
+ self->pool = (GstDucatiBufferPool *)
+ gst_mini_object_ref (GST_MINI_OBJECT (pool));
+
+ GST_BUFFER_DATA (self) =
+ gst_ducati_alloc_2d (pool->padded_width, pool->padded_height, &sz);
+ GST_BUFFER_SIZE (self) = sz;
+
+ gst_buffer_set_caps (GST_BUFFER (self), pool->caps);
+
+ return self;
+}
+
+static void
+gst_ducati_buffer_finalize (GstDucatiBuffer * self)
+{
+ GstDucatiBufferPool *pool = self->pool;
+ gboolean resuscitated = FALSE;
+
+ GST_LOG_OBJECT (pool->element, "finalizing buffer %p", self);
+
+ GST_DUCATI_BUFFERPOOL_LOCK (pool);
+ if (pool->running) {
+ resuscitated = TRUE;
+
+ GST_LOG_OBJECT (pool->element, "reviving buffer %p", self);
+ gst_buffer_ref (GST_BUFFER (self));
+
+ /* insert self into freelist */
+ self->next = pool->freelist;
+ pool->freelist = self;
+ } else {
+ GST_LOG_OBJECT (pool->element, "the pool is shutting down");
+ }
+ GST_DUCATI_BUFFERPOOL_UNLOCK (pool);
+
+ if (!resuscitated) {
+ GST_LOG_OBJECT (pool->element,
+ "buffer %p (data %p, len %u) not recovered, freeing",
+ self, GST_BUFFER_DATA (self), GST_BUFFER_SIZE (self));
+ MemMgr_Free ((void *) GST_BUFFER_DATA (self));
+ GST_BUFFER_DATA (self) = NULL;
+ gst_mini_object_unref (GST_MINI_OBJECT (pool));
+ GST_MINI_OBJECT_CLASS (buffer_parent_class)->
+ finalize (GST_MINI_OBJECT (self));
+ }
+}
+
+static void
+gst_ducati_buffer_class_init (gpointer g_class, gpointer class_data)
+{
+ GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
+
+ buffer_parent_class = g_type_class_peek_parent (g_class);
+
+ mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
+ GST_DEBUG_FUNCPTR (gst_ducati_buffer_finalize);
+}
+
+GType
+gst_ducati_buffer_get_type (void)
+{
+ static GType type;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo info = {
+ .class_size = sizeof (GstBufferClass),
+ .class_init = gst_ducati_buffer_class_init,
+ .instance_size = sizeof (GstDucatiBuffer),
+ };
+ type = g_type_register_static (GST_TYPE_BUFFER,
+ "GstDucatiBuffer", &info, 0);
+ }
+ return type;
+}
+
+/*
+ * GstDucatiBufferPool
+ */
+
+static GstMiniObjectClass *bufferpool_parent_class = NULL;
+
+/** create new bufferpool */
+GstDucatiBufferPool *
+gst_ducati_bufferpool_new (GstElement * element, GstCaps * caps)
+{
+ GstDucatiBufferPool *self = (GstDucatiBufferPool *)
+ gst_mini_object_new (GST_TYPE_DUCATIBUFFERPOOL);
+ GstStructure *s = gst_caps_get_structure (caps, 0);
+
+ self->element = gst_object_ref (element);
+ gst_structure_get_int (s, "width", &self->padded_width);
+ gst_structure_get_int (s, "height", &self->padded_height);
+ self->caps = gst_caps_ref (caps);
+ self->freelist = NULL;
+ self->lock = g_mutex_new ();
+ self->running = TRUE;
+
+ return self;
+}
+
+/** destroy existing bufferpool */
+void
+gst_ducati_bufferpool_destroy (GstDucatiBufferPool * self)
+{
+ g_return_if_fail (self);
+
+ GST_DUCATI_BUFFERPOOL_LOCK (self);
+ self->running = FALSE;
+ GST_DUCATI_BUFFERPOOL_UNLOCK (self);
+
+ GST_DEBUG_OBJECT (self->element, "destroy pool");
+
+ /* free all buffers on the freelist */
+ while (self->freelist) {
+ GstDucatiBuffer *buf = self->freelist;
+ self->freelist = buf->next;
+ gst_buffer_unref (GST_BUFFER (buf));
+ }
+
+ gst_mini_object_unref (GST_MINI_OBJECT (self));
+}
+
+/** get buffer from bufferpool, allocate new buffer if needed */
+GstDucatiBuffer *
+gst_ducati_bufferpool_get (GstDucatiBufferPool * self, GstBuffer * orig)
+{
+ GstDucatiBuffer *buf = NULL;
+
+ g_return_if_fail (self);
+
+ GST_DUCATI_BUFFERPOOL_LOCK (self);
+ if (self->running) {
+ /* re-use a buffer off the freelist if any are available
+ */
+ if (self->freelist) {
+ buf = self->freelist;
+ self->freelist = buf->next;
+ } else {
+ buf = gst_ducati_buffer_new (self);
+ }
+ buf->orig = orig;
+ }
+ GST_DUCATI_BUFFERPOOL_UNLOCK (self);
+
+ if (buf && orig) {
+ GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_TIMESTAMP (orig);
+ GST_BUFFER_DURATION (buf) = GST_BUFFER_DURATION (orig);
+ }
+
+ return buf;
+}
+
+static void
+gst_ducati_bufferpool_finalize (GstDucatiBufferPool * self)
+{
+ g_mutex_free (self->lock);
+ gst_caps_unref (self->caps);
+ gst_object_unref (self->element);
+ GST_MINI_OBJECT_CLASS (bufferpool_parent_class)->
+ finalize (GST_MINI_OBJECT (self));
+}
+
+static void
+gst_ducati_bufferpool_class_init (gpointer g_class, gpointer class_data)
+{
+ GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
+
+ bufferpool_parent_class = g_type_class_peek_parent (g_class);
+
+ mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
+ GST_DEBUG_FUNCPTR (gst_ducati_bufferpool_finalize);
+}
+
+GType
+gst_ducati_bufferpool_get_type (void)
+{
+ static GType type;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo info = {
+ .class_size = sizeof (GstMiniObjectClass),
+ .class_init = gst_ducati_bufferpool_class_init,
+ .instance_size = sizeof (GstDucatiBufferPool),
+ };
+ type = g_type_register_static (GST_TYPE_MINI_OBJECT,
+ "GstDucatiBufferPool", &info, 0);
+ }
+ return type;
+}
diff --git a/src/gstducatibufferpool.h b/src/gstducatibufferpool.h
new file mode 100644
index 0000000..cbf48e9
--- /dev/null
+++ b/src/gstducatibufferpool.h
@@ -0,0 +1,73 @@
+/*
+ * GStreamer
+ * Copyright (c) 2010, Texas Instruments Incorporated
+ *
+ * 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 __GSTDUCATIBUFFERPOOL_H__
+#define __GSTDUCATIBUFFERPOOL_H__
+
+#include "gstducati.h"
+
+G_BEGIN_DECLS
+
+GType gst_ducati_buffer_get_type (void);
+#define GST_TYPE_DUCATIBUFFER (gst_ducati_buffer_get_type())
+#define GST_IS_DUCATIBUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DUCATIBUFFER))
+#define GST_DUCATIBUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DUCATIBUFFER, GstDucatiBuffer))
+
+GType gst_ducati_bufferpool_get_type (void);
+#define GST_TYPE_DUCATIBUFFERPOOL (gst_ducati_bufferpool_get_type())
+#define GST_IS_DUCATIBUFFERPOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DUCATIBUFFERPOOL))
+#define GST_DUCATIBUFFERPOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DUCATIBUFFERPOOL, GstDucatiBufferPool))
+
+typedef struct _GstDucatiBufferPool GstDucatiBufferPool;
+typedef struct _GstDucatiBuffer GstDucatiBuffer;
+
+struct _GstDucatiBufferPool
+{
+ GstMiniObject parent;
+
+ /* output (padded) size including any codec padding: */
+ gint padded_width, padded_height;
+
+ GstCaps *caps;
+ GMutex *lock;
+ gboolean running; /* with lock */
+ GstElement *element; /* the element that owns us.. */
+ GstDucatiBuffer *freelist; /* list of available buffers */
+};
+
+GstDucatiBufferPool * gst_ducati_bufferpool_new (GstElement * element, GstCaps * caps);
+void gst_ducati_bufferpool_destroy (GstDucatiBufferPool * pool);
+GstDucatiBuffer * gst_ducati_bufferpool_get (GstDucatiBufferPool * self, GstBuffer * orig);
+
+#define GST_DUCATI_BUFFERPOOL_LOCK(self) g_mutex_lock ((self)->lock)
+#define GST_DUCATI_BUFFERPOOL_UNLOCK(self) g_mutex_unlock ((self)->lock)
+
+struct _GstDucatiBuffer {
+ GstBuffer parent;
+
+ GstDucatiBufferPool *pool; /* buffer-pool that this buffer belongs to */
+ GstBuffer *orig; /* original buffer, if we need to copy output */
+ GstDucatiBuffer *next; /* next in freelist, if not in use */
+};
+
+GstBuffer * gst_ducati_buffer_get (GstDucatiBuffer * self);
+
+G_END_DECLS
+
+#endif /* __GSTDUCATIBUFFERPOOL_H__ */
diff --git a/src/gstducatividdec.c b/src/gstducatividdec.c
index ed6c7a5..486efd8 100644
--- a/src/gstducatividdec.c
+++ b/src/gstducatividdec.c
@@ -109,6 +109,11 @@ engine_open (GstDucatiVidDec * self)
static void
codec_delete (GstDucatiVidDec * self)
{
+ if (self->pool) {
+ gst_ducati_bufferpool_destroy (self->pool);
+ self->pool = NULL;
+ }
+
if (self->codec) {
VIDDEC3_delete(self->codec);
self->codec = NULL;
@@ -174,6 +179,17 @@ codec_create (GstDucatiVidDec * self)
return TRUE;
}
+static inline GstBuffer *
+codec_bufferpool_get (GstDucatiVidDec * self, GstBuffer * buf)
+{
+ if (G_UNLIKELY (!self->pool)) {
+ GST_DEBUG_OBJECT (self, "creating bufferpool");
+ self->pool = gst_ducati_bufferpool_new (GST_ELEMENT (self),
+ GST_PAD_CAPS (self->srcpad));
+ }
+ return GST_BUFFER (gst_ducati_bufferpool_get (self->pool, buf));
+}
+
static XDAS_Int32
codec_prepare_outbuf (GstDucatiVidDec * self, GstBuffer * buf)
{
@@ -191,7 +207,8 @@ codec_prepare_outbuf (GstDucatiVidDec * self, GstBuffer * buf)
uv_type = gst_ducati_get_mem_type (uv_paddr);
if ((y_type < 0) || (uv_type < 0)) {
- return 0;
+ GST_DEBUG_OBJECT (self, "non TILER buffer, fallback to bufferpool");
+ return codec_prepare_outbuf (self, codec_bufferpool_get (self, buf));
}
if (!self->outBufs->numBufs) {
@@ -208,7 +225,11 @@ codec_prepare_outbuf (GstDucatiVidDec * self, GstBuffer * buf)
/* verify output buffer type matches what we've already given
* to the codec
*/
- // TODO
+ if ((self->outBufs->descs[0].memType != y_type) ||
+ (self->outBufs->descs[1].memType != uv_type)) {
+ GST_DEBUG_OBJECT (self, "buffer mismatch, fallback to bufferpool");
+ return codec_prepare_outbuf (self, codec_bufferpool_get (self, buf));
+ }
}
self->outBufs->descs[0].buf = (XDAS_Int8 *) y_paddr;
@@ -276,6 +297,9 @@ codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush)
outbuf = codec_get_outbuf (self, self->outArgs->outputID[i]);
if (send) {
+ if (GST_IS_DUCATIBUFFER (outbuf)) {
+ outbuf = gst_ducati_buffer_get (GST_DUCATIBUFFER (outbuf));
+ }
GST_DEBUG_OBJECT (self, "got buffer: %d %p (%" GST_TIME_FORMAT ")",
i, outbuf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
gst_pad_push (self->srcpad, outbuf);
@@ -544,11 +568,8 @@ gst_ducati_viddec_chain (GstPad * pad, GstBuffer * buf)
GST_PAD_CAPS (self->srcpad), &outbuf);
if (ret != GST_FLOW_OK) {
- /* TODO: if we had our own buffer class, we could allocate our own
- * output buffer from TILER...
- */
- GST_WARNING_OBJECT (self, "TODO: allocate output TILER buffer");
- return ret;
+ outbuf = codec_bufferpool_get (self, NULL);
+ ret = GST_FLOW_OK;
}
if (G_UNLIKELY (!self->codec)) {
diff --git a/src/gstducatividdec.h b/src/gstducatividdec.h
index 9be1d91..4075da3 100644
--- a/src/gstducatividdec.h
+++ b/src/gstducatividdec.h
@@ -23,6 +23,7 @@
#include <gst/gst.h>
#include "gstducati.h"
+#include "gstducatibufferpool.h"
G_BEGIN_DECLS
@@ -47,6 +48,8 @@ struct _GstDucatiVidDec
GstPad *sinkpad, *srcpad;
+ GstDucatiBufferPool *pool;
+
/* minimum output size required by the codec: */
gint outsize;