diff --git a/omx/Makefile.am b/omx/Makefile.am index 4ca928e..de5ee7c 100755 --- a/omx/Makefile.am +++ b/omx/Makefile.am @@ -48,6 +48,7 @@ libgstomx_la_SOURCES = gstomx.c gstomx.h \ gstomx_filereadersrc.c gstomx_filereadersrc.h \ swcsc.c swcsc.h \ gstperf.c gstperf.h \ + gstomxbufferalloc.c gstomxbufferalloc.h \ gstomx_buffertransport.c gstomx_buffertransport.h \ gstomx_base_vfpc.c gstomx_base_vfpc.h \ gstomx_base_vfpc2.c gstomx_base_vfpc2.h \ diff --git a/omx/gstomx.c b/omx/gstomx.c index 98bcdfa..406af9b 100755 --- a/omx/gstomx.c +++ b/omx/gstomx.c @@ -64,6 +64,8 @@ #include "gstomx_vc1dec.h" #include "gstomx_videomixer.h" +#include "gstomxbufferalloc.h" + #include "config.h" GST_DEBUG_CATEGORY (gstomx_debug); @@ -118,6 +120,7 @@ static TableItem element_table[] = // { "omx_volume", "libomxil-bellagio.so.0", "OMX.st.volume.component", NULL, GST_RANK_NONE, gst_omx_volume_get_type }, { "swcsc", "libOMX_Core.so", NULL, NULL, GST_RANK_PRIMARY, gst_swcsc_get_type }, { "gstperf", "libOMX_Core.so", NULL, NULL, GST_RANK_PRIMARY, gst_perf_get_type }, + { "omxbufferalloc", "libOMX_Core.so", NULL, NULL, GST_RANK_PRIMARY, gst_omx_buffer_alloc_get_type }, { "omx_scaler", "libOMX_Core.so", "OMX.TI.VPSSM3.VFPC.INDTXSCWB", "", GST_RANK_PRIMARY, gst_omx_scaler_get_type }, { "omx_mdeiscaler", "libOMX_Core.so", "OMX.TI.VPSSM3.VFPC.DEIMDUALOUT", "", GST_RANK_PRIMARY, gst_omx_mdeiscaler_get_type }, { "omx_hdeiscaler", "libOMX_Core.so", "OMX.TI.VPSSM3.VFPC.DEIHDUALOUT", "", GST_RANK_PRIMARY, gst_omx_hdeiscaler_get_type }, diff --git a/omx/gstomx_buffertransport.c b/omx/gstomx_buffertransport.c index 8ad03d5..3850ed5 100755 --- a/omx/gstomx_buffertransport.c +++ b/omx/gstomx_buffertransport.c @@ -98,13 +98,16 @@ release_buffer (GOmxPort *port, OMX_BUFFERHEADERTYPE *omx_buffer) break; } } +#include static void gst_omxbuffertransport_finalize(GstBuffer *gstbuffer) { GstOmxBufferTransport *self = GST_OMXBUFFERTRANSPORT(gstbuffer); int ii; - GST_LOG("begin\n"); + GST_LOG("begin\n"); + static guint64 beftime = 0; + if(self->omxbuffer) release_buffer (self->port, self->omxbuffer); for(ii = 0; ii < self->numAdditionalHeaders; ii++) { @@ -116,10 +119,23 @@ static void gst_omxbuffertransport_finalize(GstBuffer *gstbuffer) free(self->addHeader); //printf("free\n"); } + if(self->parent) + gst_buffer_unref(self->parent); + + if(self->bufSem) { + struct timeval tv; + guint64 afttime; + gettimeofday(&tv, NULL); + afttime = (tv.tv_sec * 1000000 + tv.tv_usec); + //printf("sem up:%lld\n",(afttime-beftime) ); + beftime = afttime; + g_sem_up(self->bufSem); + } + self->addHeader = NULL; self->omxbuffer = NULL; self->port = NULL; - + self->parent = NULL; /* Call GstBuffer's finalize routine, so our base class can do it's cleanup * as well. If we don't do this, we'll have a memory leak that is very * difficult to track down. @@ -153,12 +169,47 @@ GstBuffer* gst_omxbuffertransport_new (GOmxPort *port, OMX_BUFFERHEADERTYPE *buf tdt_buf->numAdditionalHeaders = 0; tdt_buf->addHeader = NULL; + tdt_buf->parent = NULL; + tdt_buf->bufSem = NULL; + + GST_LOG("end new\n"); + + return GST_BUFFER(tdt_buf); +} + +GstBuffer* gst_omxbuffertransport_clone (GstBuffer *parent, GOmxPort *port) +{ + GstOmxBufferTransport *tdt_buf; + tdt_buf = (GstOmxBufferTransport*) + gst_mini_object_new(GST_TYPE_OMXBUFFERTRANSPORT); + + g_return_val_if_fail(tdt_buf != NULL, NULL); + + GST_BUFFER_SIZE(tdt_buf) = GST_BUFFER_SIZE(parent); + GST_BUFFER_DATA(tdt_buf) = GST_BUFFER_DATA(parent); + GST_BUFFER_CAPS(GST_BUFFER (tdt_buf)) = gst_caps_ref (GST_BUFFER_CAPS(parent)); + GST_BUFFER_TIMESTAMP(tdt_buf) = GST_BUFFER_TIMESTAMP(parent); + GST_BUFFER_DURATION(tdt_buf) = GST_BUFFER_DURATION(parent); + + if (GST_BUFFER_DATA(tdt_buf) == NULL) { + gst_mini_object_unref(GST_MINI_OBJECT(tdt_buf)); + return NULL; + } + + tdt_buf->omxbuffer = NULL; + tdt_buf->port = port; + tdt_buf->numAdditionalHeaders = 0; + tdt_buf->addHeader = NULL; + tdt_buf->bufSem = NULL; + tdt_buf->parent = parent; GST_LOG("end new\n"); return GST_BUFFER(tdt_buf); + } + void gst_omxbuffertransport_set_additional_headers (GstOmxBufferTransport *self ,guint numHeaders,OMX_BUFFERHEADERTYPE **buffer) { int ii; @@ -180,4 +231,9 @@ void gst_omxbuffertransport_set_additional_headers (GstOmxBufferTransport *self return ; } +void gst_omxbuffertransport_set_bufsem (GstOmxBufferTransport *self ,GSem *sem) +{ + self->bufSem = sem; + return ; +} diff --git a/omx/gstomx_buffertransport.h b/omx/gstomx_buffertransport.h index 74f1416..5f1c0e9 100644 --- a/omx/gstomx_buffertransport.h +++ b/omx/gstomx_buffertransport.h @@ -61,6 +61,8 @@ struct _GstOmxBufferTransport { GOmxPort *port; guint numAdditionalHeaders; OMX_BUFFERHEADERTYPE **addHeader; + GstBuffer *parent; + GSem *bufSem; }; struct _GstOmxBufferTransportClass { diff --git a/omx/gstomx_port.c b/omx/gstomx_port.c index 44ad21b..b0f2e01 100755 --- a/omx/gstomx_port.c +++ b/omx/gstomx_port.c @@ -69,6 +69,7 @@ g_omx_port_new (GOmxCore *core, const gchar *name, guint index) port->enabled = TRUE; port->queue = async_queue_new (); port->mutex = g_mutex_new (); + port->cond = g_cond_new(); port->ignore_count = 0; port->n_offset = 0; @@ -83,6 +84,7 @@ g_omx_port_free (GOmxPort *port) DEBUG (port, "begin"); g_mutex_free (port->mutex); + g_cond_free(port->cond); async_queue_free (port->queue); g_free (port->name); @@ -355,8 +357,12 @@ g_omx_port_push_buffer (GOmxPort *port, /* Avoid a race condition of pAppPrivate getting set to null after the buffer is submitted back again */ OMX_PTR appPrivate = omx_buffer->pAppPrivate; - omx_buffer->pAppPrivate = NULL; - gst_buffer_unref (appPrivate); + //omx_buffer->pAppPrivate = NULL; + g_mutex_lock(port->mutex); + GST_BUFFER_FLAG_UNSET(appPrivate,GST_BUFFER_FLAG_BUSY); + gst_buffer_unref (appPrivate); + g_cond_signal(port->cond); + g_mutex_unlock(port->mutex); } else async_queue_push (port->queue, omx_buffer); } @@ -723,7 +729,7 @@ send_prep_eos_event (GOmxPort *port, OMX_BUFFERHEADERTYPE *omx_buffer, GstEvent static OMX_BUFFERHEADERTYPE * get_input_buffer_header (GOmxPort *port, GstBuffer *src) { - OMX_BUFFERHEADERTYPE *omx_buffer; + OMX_BUFFERHEADERTYPE *omx_buffer,*tmp; int index; index = omxbuffer_index(port, GST_BUFFER_DATA (src)); @@ -731,7 +737,11 @@ get_input_buffer_header (GOmxPort *port, GstBuffer *src) omx_buffer = port->buffers[index]; omx_buffer->pBuffer = GST_BUFFER_DATA(src); - omx_buffer->nOffset = GST_GET_OMXBUFFER(src)->nOffset; + tmp = GST_GET_OMXBUFFER(src); + if(tmp) + omx_buffer->nOffset = tmp->nOffset; + else + omx_buffer->nOffset = 0; omx_buffer->nFilledLen = GST_BUFFER_SIZE (src); omx_buffer->pAppPrivate = gst_buffer_ref (src); diff --git a/omx/gstomx_port.h b/omx/gstomx_port.h index 7b56906..563c70d 100644 --- a/omx/gstomx_port.h +++ b/omx/gstomx_port.h @@ -30,6 +30,8 @@ G_BEGIN_DECLS +#define GST_BUFFER_FLAG_BUSY (GST_BUFFER_FLAG_LAST << 1) + /* Typedefs. */ typedef enum GOmxPortType GOmxPortType; @@ -88,6 +90,8 @@ struct GOmxPort /** if omx_allocate flag is not set then structure will contain upstream omx buffer pointer information */ OmxBufferInfo *share_buffer_info; + + GCond *cond; }; /* Macros. */ diff --git a/omx/gstomx_videomixer.c b/omx/gstomx_videomixer.c index 023a428..97ccf21 100755 --- a/omx/gstomx_videomixer.c +++ b/omx/gstomx_videomixer.c @@ -34,6 +34,7 @@ enum ARG_NUM_INPUT_BUFFERS, ARG_NUM_OUTPUT_BUFFERS, ARG_PORT_INDEX, + ARG_FRAME_RATE }; static void init_interfaces (GType type); @@ -191,10 +192,12 @@ change_state (GstElement *element, g_omx_port_finish (self->in_port[ii]); g_omx_port_finish (self->out_port[ii]); } + //printf("setting EOS to true\n"); + self->eos = TRUE; for(ii = 0; ii < NUM_PORTS; ii++) async_queue_disable (self->chInfo[ii].queue); - - // printf("Waiting for ip thread to exit!!\n"); + //printf("Waiting for ip thread to exit..semup!!\n"); + g_sem_up(self->bufferSem); pthread_join(self->input_loop, &thread_ret); for(ii = 0; ii < NUM_PORTS; ii++) @@ -303,6 +306,9 @@ set_property (GObject *obj, if (!self->port_configured) //gstomx_vfpc_set_port_index (obj, self->port_index); break; + case ARG_FRAME_RATE: + self->framerate_num = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; @@ -338,7 +344,7 @@ get_property (GObject *obj, { OMX_PARAM_PORTDEFINITIONTYPE param; GOmxPort *port = (prop_id == ARG_NUM_INPUT_BUFFERS) ? - self->in_port : self->out_port; + self->in_port[0] : self->out_port[0]; G_OMX_PORT_GET_DEFINITION (port, ¶m); @@ -440,6 +446,11 @@ type_class_init (gpointer g_class, g_param_spec_uint ("port-index", "port index", "input/output start port index", 0, 8, 0, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, ARG_FRAME_RATE, + g_param_spec_uint ("framerate", "Frame Rate", + "The rate at which the mixer ocmponent would operate", + 1, 60, 15, G_PARAM_WRITABLE)); } } @@ -755,13 +766,16 @@ vidmix_port_recv (GstOmxVideoMixer *self) GST_BUFFER_SIZE(buf) = GST_BUFFER_SIZE(buf)*2; if (port->core->use_timestamps) { - GST_BUFFER_TIMESTAMP (buf) = gst_util_uint64_scale_int ( + /*GST_BUFFER_TIMESTAMP (buf) = gst_util_uint64_scale_int ( omx_buffer->nTimeStamp, - GST_SECOND, OMX_TICKS_PER_SECOND); + GST_SECOND, OMX_TICKS_PER_SECOND);*/ + GST_BUFFER_TIMESTAMP (buf) = self->timestamp; + GST_BUFFER_DURATION (buf) = self->duration; + self->timestamp += self->duration; } gst_omxbuffertransport_set_additional_headers (buf ,NUM_PORTS -1,&omx_bufferHdr); - + gst_omxbuffertransport_set_bufsem (buf ,self->bufferSem); port->n_offset = omx_buffer->nOffset; ret = buf; @@ -810,6 +824,10 @@ output_loop (gpointer data) { GstBuffer *buf = GST_BUFFER (obj); + /*printf("push : %" + GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT"\n", + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP(buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION(buf)));*/ ret = bclass->push_buffer (self, buf); GST_DEBUG_OBJECT (self, "ret=%s", gst_flow_get_name (ret)); @@ -986,7 +1004,7 @@ vidmix_port_allocate_buffers (GstOmxVideoMixer *self) size = param.nBufferSize; port->buffers = g_new0 (OMX_BUFFERHEADERTYPE *, port->num_buffers); - + printf("Input num bufffers:%d\n",port->num_buffers); for (i = 0; i < port->num_buffers; i++) { gpointer buffer_data = NULL; @@ -1039,6 +1057,7 @@ vidmix_port_allocate_buffers (GstOmxVideoMixer *self) g_return_if_fail (port->buffers[i]); //printf("allocated buffer:%p\n",port->buffers[i]->pBuffer); } + self->bufferSem = g_sem_new_with_value(port->num_buffers); }else { G_OMX_PORT_GET_DEFINITION (port, ¶m); size = param.nBufferSize; @@ -1105,6 +1124,9 @@ static void* vidmix_input_loop(void *arg) { GOmxCore *gomx; int kk=0; gint sent; + struct timeval tv; + guint64 afttime; + guint64 beftime; port = self->in_port[0]; gomx = port->core; @@ -1163,29 +1185,71 @@ static void* vidmix_input_loop(void *arg) { while(TRUE) { + OMX_BUFFERHEADERTYPE *omx_buffer; + //printf("sem cnt:%d\n",self->bufferSem->counter); + + /*gettimeofday(&tv, NULL); + beftime = (tv.tv_sec * 1000000 + tv.tv_usec);*/ + g_sem_down(self->bufferSem); + /*gettimeofday(&tv, NULL); + afttime = (tv.tv_sec * 1000000 + tv.tv_usec); + printf("Wait:%lld\n",(afttime-beftime));*/ for(ii = 0; ii < NUM_PORTS; ii++) { port = self->in_port[ii]; gomx = port->core; buf = NULL; //printf("pop queue:%d\n",ii); if(self->chInfo[ii].eos == FALSE) { - buf = (GstBuffer *)async_queue_pop_full(self->chInfo[ii].queue,TRUE,FALSE); + //printf("force is FALSE\n"); + buf = (GstBuffer *)async_queue_pop_full(self->chInfo[ii].queue,FALSE,FALSE); if(buf == NULL) { + + if(self->eos == TRUE) { + printf("goto leave!!\n"); + goto leave; + } + //printf("NULL buffer...ip exiting!!\n"); - goto leave; + //printf("reuse:%d, buffer:%p!!\n",ii,self->chInfo[ii].lastBuf); + //buf = gst_buffer_ref(self->chInfo[ii].lastBuf); + //omx_buffer = GST_GET_OMXBUFFER(self->chInfo[ii].lastBuf); + g_mutex_lock(port->mutex); + //printf("wait:%d,buffer:%p\n",ii,self->chInfo[ii].lastBuf); + while(GST_BUFFER_FLAG_IS_SET(self->chInfo[ii].lastBuf,GST_BUFFER_FLAG_BUSY)) + g_cond_wait(port->cond,port->mutex); + //printf("wait done:%d\n",ii); + g_mutex_unlock(port->mutex); + + buf = (self->chInfo[ii].lastBuf); + //goto leave; + }else { + if(self->chInfo[ii].lastBuf) { + //printf("unref buffer:%p, refcnt:%d!!\n",self->chInfo[ii].lastBuf,GST_MINI_OBJECT_CAST(self->chInfo[ii].lastBuf)->refcount); + gst_buffer_unref(self->chInfo[ii].lastBuf); + } + //self->chInfo[ii].lastBuf = gst_buffer_ref(buf); + self->chInfo[ii].lastBuf = buf; } + + /*omx_buffer = GST_GET_OMXBUFFER(buf); + omx_buffer->nFlags |= OMX_BUFFERFLAG_BUSY;*/ //printf("send: %d:%p!!\n",ii,buf); + GST_BUFFER_FLAG_SET(buf,GST_BUFFER_FLAG_BUSY); sent = g_omx_port_send (port, buf); - gst_buffer_unref (buf); + //gst_buffer_unref (buf); } - + //sched_yield(); } } leave: - //printf("leaving ip thread!!\n"); + printf("leaving ip thread!!\n"); + for(ii = 0; ii < NUM_PORTS; ii++) + if(self->chInfo[ii].lastBuf) + gst_buffer_unref(self->chInfo[ii].lastBuf); + return NULL; } @@ -1229,7 +1293,7 @@ pad_chain (GstPad *pad, leave: GST_LOG_OBJECT (self, "end"); - //printf("leaving!!\n"); + // printf("leaving :%d!!\n",ch_info->idx); return ret; /* special conditions */ @@ -1513,7 +1577,7 @@ sink_setcaps (GstPad *pad, { ch_info->in_stride = gstomx_calculate_stride (ch_info->in_width, format); } - +#if 0 { const GValue *framerate = NULL; framerate = gst_structure_get_value (structure, "framerate"); @@ -1522,13 +1586,15 @@ sink_setcaps (GstPad *pad, self->framerate_num = gst_value_get_fraction_numerator (framerate); self->framerate_denom = gst_value_get_fraction_denominator (framerate); - omx_base->duration = gst_util_uint64_scale_int(GST_SECOND, + /* omx_base->duration = gst_util_uint64_scale_int(GST_SECOND, gst_value_get_fraction_denominator (framerate), gst_value_get_fraction_numerator (framerate)); GST_DEBUG_OBJECT (self, "Nominal frame duration =%"GST_TIME_FORMAT, - GST_TIME_ARGS (omx_base->duration)); + GST_TIME_ARGS (omx_base->duration));*/ } } +#endif + self->duration = ((guint64)GST_SECOND/self->framerate_num); if (self->sink_setcaps) self->sink_setcaps (pad, caps); @@ -1630,6 +1696,7 @@ type_instance_init (GTypeInstance *instance, self->chInfo[ii].queue = async_queue_new (); self->chInfo[ii].idx = ii; self->chInfo[ii].eos = FALSE; + self->chInfo[ii].lastBuf = NULL; printf("queue_%d : %p\n",ii,self->chInfo[ii].queue); gst_pad_set_element_private(self->sinkpad[ii], &(self->chInfo[ii])); @@ -1650,9 +1717,13 @@ type_instance_init (GTypeInstance *instance, gst_pad_set_setcaps_function (self->srcpad, GST_DEBUG_FUNCPTR (src_setcaps)); - - self->duration = GST_CLOCK_TIME_NONE; - printf("In instance init/...done!!\n"); + + self->framerate_num = 15; + self->framerate_denom = 1; + self->timestamp = 0; + /*printf("duration:%lld, in time : %" + GST_TIME_FORMAT "\n",self->duration,GST_TIME_ARGS(self->duration)); + printf("In instance init/...done!!\n");*/ GST_LOG_OBJECT (self, "end"); } diff --git a/omx/gstomx_videomixer.h b/omx/gstomx_videomixer.h index 9255e08..7a45c01 100755 --- a/omx/gstomx_videomixer.h +++ b/omx/gstomx_videomixer.h @@ -49,6 +49,7 @@ typedef struct ip_params { gint in_width, in_height, in_stride; AsyncQueue *queue; gboolean eos; + GstBuffer *lastBuf; } ip_params ; @@ -88,6 +89,8 @@ struct GstOmxVideoMixer //gpointer g_class; ip_params chInfo[NUM_PORTS]; guint numEosPending; + GSem *bufferSem; + GstClockTime timestamp; }; diff --git a/omx/gstomxbufferalloc.c b/omx/gstomxbufferalloc.c new file mode 100644 index 0000000..e92fd9d --- /dev/null +++ b/omx/gstomxbufferalloc.c @@ -0,0 +1,348 @@ +/* + * GStreamer + * Copyright (C) 2005 Thomas Vander Stichele + * Copyright (C) 2005 Ronald S. Bultje + * Copyright (C) 2011 prashant <> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Alternatively, the contents of this file may be used under the + * GNU Lesser General Public License Version 2.1 (the "LGPL"), in + * which case the following provisions apply instead of the ones + * mentioned above: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-omxbufferalloc + * + * FIXME:Describe omxbufferalloc here. + * + * + * Example launch line + * |[ + * gst-launch -v -m fakesrc ! omxbufferalloc ! fakesink silent=TRUE + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include "gstomx.h" +#include "gstomx_interface.h" + +#include "gstomxbufferalloc.h" + + +GST_DEBUG_CATEGORY_STATIC (gst_omx_buffer_alloc_debug); +//#define GST_CAT_DEFAULT gst_omx_buffer_alloc_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_SILENT, + PROP_NUMBUFFERS +}; + +/* the capabilities of the inputs and outputs. + * + * describe the real formats here. + */ +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("ANY") + ); + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("ANY") + ); + +GST_BOILERPLATE (GstomxBufferAlloc, gst_omx_buffer_alloc, GstElement, + GST_TYPE_ELEMENT); + +static void gst_omx_buffer_alloc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_omx_buffer_alloc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_omx_buffer_alloc_set_caps (GstPad * pad, GstCaps * caps); +static GstFlowReturn gst_omx_buffer_alloc_chain (GstPad * pad, GstBuffer * buf); + +GstFlowReturn +gst_omx_buffer_alloc_bufferalloc (GstPad *pad, guint64 offset, guint size, + GstCaps *caps, GstBuffer **buf); + +static GstStateChangeReturn +gst_omx_buffer_alloc_change_state (GstElement *element, + GstStateChange transition); + + + +/* GObject vmethod implementations */ + +static void +gst_omx_buffer_alloc_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + gst_element_class_set_details_simple(element_class, + "omxBufferAlloc", + "FIXME:Generic", + "FIXME:Generic Template Element", + "prashant <>"); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); +} + +/* initialize the omxbufferalloc's class */ +static void +gst_omx_buffer_alloc_class_init (GstomxBufferAllocClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->set_property = gst_omx_buffer_alloc_set_property; + gobject_class->get_property = gst_omx_buffer_alloc_get_property; + gstelement_class->change_state = gst_omx_buffer_alloc_change_state; + + g_object_class_install_property (gobject_class, PROP_NUMBUFFERS, + g_param_spec_uint ("numBuffers", "number of buffers", + "Number of buffers to be allocated by component", + 1, 16, 10, G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", + FALSE, G_PARAM_READWRITE)); + +} + +/* initialize the new element + * instantiate pads and add them to element + * set pad calback functions + * initialize instance structure + */ +static void +gst_omx_buffer_alloc_init (GstomxBufferAlloc * filter, + GstomxBufferAllocClass * gclass) +{ + filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink"); + gst_pad_set_setcaps_function (filter->sinkpad, + GST_DEBUG_FUNCPTR(gst_omx_buffer_alloc_set_caps)); + gst_pad_set_getcaps_function (filter->sinkpad, + GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps)); + gst_pad_set_chain_function (filter->sinkpad, + GST_DEBUG_FUNCPTR(gst_omx_buffer_alloc_chain)); + + gst_pad_set_bufferalloc_function(filter->sinkpad,GST_DEBUG_FUNCPTR(gst_omx_buffer_alloc_bufferalloc)); + + filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); + gst_pad_set_getcaps_function (filter->srcpad, + GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps)); + + gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); + gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); + filter->silent = FALSE; + filter->out_port.num_buffers = 10; + filter->out_port.always_copy = FALSE; + filter->cnt = 0; + filter->out_port.buffers = NULL; +} + +static void +gst_omx_buffer_alloc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstomxBufferAlloc *filter = GST_OMXBUFFERALLOC (object); + + switch (prop_id) { + case PROP_SILENT: + filter->silent = g_value_get_boolean (value); + break; + case PROP_NUMBUFFERS: + filter->out_port.num_buffers = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_omx_buffer_alloc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstomxBufferAlloc *filter = GST_OMXBUFFERALLOC (object); + + switch (prop_id) { + case PROP_SILENT: + g_value_set_boolean (value, filter->silent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* GstElement vmethod implementations */ + +/* this function handles the link with other elements */ +static gboolean +gst_omx_buffer_alloc_set_caps (GstPad * pad, GstCaps * caps) +{ + GstomxBufferAlloc *filter; + GstPad *otherpad; + + filter = GST_OMXBUFFERALLOC (gst_pad_get_parent (pad)); + otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad; + gst_object_unref (filter); + + return gst_pad_set_caps (otherpad, caps); +} + +/* chain function + * this function does the actual processing + */ +static GstFlowReturn +gst_omx_buffer_alloc_chain (GstPad * pad, GstBuffer * buf) +{ + GstomxBufferAlloc *filter; + + filter = GST_OMXBUFFERALLOC (GST_OBJECT_PARENT (pad)); + + buf = gst_omxbuffertransport_clone (buf, &(filter->out_port)); + + /* just push out the incoming buffer without touching it */ + return gst_pad_push (filter->srcpad, buf); +} + +void +gst_omx_buffer_alloc_allocate_buffers (GstomxBufferAlloc *filter, guint size) +{ + guint ii; + guint numBufs; + + numBufs = filter->out_port.num_buffers; + printf("allocating %d buffers of size:%d!!\n",numBufs,size); + filter->out_port.buffers = g_new0 (OMX_BUFFERHEADERTYPE *, numBufs); + filter->heap = SharedRegion_getHeap(2); + + for(ii = 0; ii < numBufs; ii++) { + filter->out_port.buffers[ii] = malloc(sizeof(OMX_BUFFERHEADERTYPE)); + filter->out_port.buffers[ii]->pBuffer = Memory_alloc (filter->heap, size, 128, NULL); + printf("allocated outbuf:%p\n",filter->out_port.buffers[ii]->pBuffer); + } + filter->allocSize = size; + + return; +} + +GstFlowReturn +gst_omx_buffer_alloc_bufferalloc (GstPad *pad, guint64 offset, guint size, + GstCaps *caps, GstBuffer **buf) +{ + GstomxBufferAlloc *filter; + filter = GST_OMXBUFFERALLOC (GST_OBJECT_PARENT (pad)); + if(filter->out_port.buffers == NULL) + gst_omx_buffer_alloc_allocate_buffers (filter,size); + + *buf = gst_buffer_new(); + GST_BUFFER_DATA(*buf) = filter->out_port.buffers[filter->cnt++]->pBuffer; + GST_BUFFER_SIZE(*buf) = size; + GST_BUFFER_CAPS(*buf) = caps; + return; +} + +static GstStateChangeReturn +gst_omx_buffer_alloc_change_state (GstElement *element, + GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstomxBufferAlloc *filter = GST_OMXBUFFERALLOC (element); + guint ii; + switch (transition) + { + case GST_STATE_CHANGE_NULL_TO_READY: + OMX_Init (); + break; + + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + if (ret == GST_STATE_CHANGE_FAILURE) + goto leave; + + switch (transition) + { + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + for(ii = 0; ii < filter->out_port.num_buffers; ii++) { + Memory_free(filter->heap,filter->out_port.buffers[ii]->pBuffer,filter->allocSize); + } + g_free(filter->out_port.buffers); + OMX_Deinit(); + break; + + default: + break; + } + +leave: + return ret; +} + + + + diff --git a/omx/gstomxbufferalloc.h b/omx/gstomxbufferalloc.h new file mode 100644 index 0000000..fbd9573 --- /dev/null +++ b/omx/gstomxbufferalloc.h @@ -0,0 +1,96 @@ +/* + * GStreamer + * Copyright (C) 2005 Thomas Vander Stichele + * Copyright (C) 2005 Ronald S. Bultje + * Copyright (C) 2011 prashant <> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Alternatively, the contents of this file may be used under the + * GNU Lesser General Public License Version 2.1 (the "LGPL"), in + * which case the following provisions apply instead of the ones + * mentioned above: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_OMXBUFFERALLOC_H__ +#define __GST_OMXBUFFERALLOC_H__ + +#include +#include "gstomx_util.h" + +#include +#include + + +G_BEGIN_DECLS + +/* #defines don't like whitespacey bits */ +#define GST_TYPE_OMXBUFFERALLOC \ + (gst_omx_buffer_alloc_get_type()) +#define GST_OMXBUFFERALLOC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMXBUFFERALLOC,GstomxBufferAlloc)) +#define GST_OMXBUFFERALLOC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMXBUFFERALLOC,GstomxBufferAllocClass)) +#define GST_IS_OMXBUFFERALLOC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMXBUFFERALLOC)) +#define GST_IS_OMXBUFFERALLOC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMXBUFFERALLOC)) + +typedef struct _GstomxBufferAlloc GstomxBufferAlloc; +typedef struct _GstomxBufferAllocClass GstomxBufferAllocClass; + +struct _GstomxBufferAlloc +{ + GstElement element; + + GstPad *sinkpad, *srcpad; + + gboolean silent; + + GOmxPort out_port; + guint cnt; + IHeap_Handle heap; + guint allocSize; +}; + +struct _GstomxBufferAllocClass +{ + GstElementClass parent_class; +}; + +GType gst_omx_buffer_alloc_get_type (void); + +G_END_DECLS + +#endif /* __GST_OMXBUFFERALLOC_H__ */ diff --git a/util/sem.c b/util/sem.c index 2ac6fac..fac8282 100644 --- a/util/sem.c +++ b/util/sem.c @@ -36,6 +36,19 @@ g_sem_new (void) return sem; } +GSem * +g_sem_new_with_value (gint value) +{ + GSem *sem; + + sem = g_new (GSem, 1); + sem->condition = g_cond_new (); + sem->mutex = g_mutex_new (); + sem->counter = value; + + return sem; +} + void g_sem_free (GSem *sem) {