Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'ti-branch' into master (update to revision 1031 from TI…

… GST OMX project)
  • Loading branch information...
commit 05c61ff812ea245824448c2544a1cbb4a5abce1b 2 parents a6f37ae + 54d5411
dchaverri authored
View
22 omx/Makefile.am
@@ -48,17 +48,17 @@ libgstomx_la_SOURCES = gstomx.c gstomx.h \
gstomx_videosink.c gstomx_videosink.h \
gstomx_base_src.c gstomx_base_src.h \
gstomx_filereadersrc.c gstomx_filereadersrc.h \
- swcsc.c swcsc.h \
- gstperf.c gstperf.h \
- gstomx_buffertransport.c gstomx_buffertransport.h \
- gstomx_base_vfpc.c gstomx_base_vfpc.h \
- gstomx_base_vfpc2.c gstomx_base_vfpc2.h \
- gstomx_base_ctrl.c gstomx_base_ctrl.h \
- gstomx_scaler.c gstomx_scaler.h \
- gstomx_deiscaler.c gstomx_deiscaler.h \
- gstomx_noisefilter.c gstomx_noisefilter.h \
- gstomx_videomixer.c gstomx_videomixer.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 \
+ gstomx_base_ctrl.c gstomx_base_ctrl.h \
+ gstomx_scaler.c gstomx_scaler.h \
+ gstomx_deiscaler.c gstomx_deiscaler.h \
+ gstomx_noisefilter.c gstomx_noisefilter.h \
+ gstomx_videomixer.c gstomx_videomixer.h
libgstomx_la_LIBADD = $(OMXCORE_LIBS) $(GST_LIBS) $(GST_BASE_LIBS) -lgstvideo-0.10 $(top_builddir)/util/libutil.la
libgstomx_la_CFLAGS = $(OMXCORE_CFLAGS) -DUSE_OMXTICORE $(OMXTIAUDIODEC_CFLAGS) $(USE_OMXTIAUDIODEC) $(GST_CFLAGS) $(GST_BASE_CFLAGS) -I$(top_srcdir)/util
View
15 omx/gstomx.c
@@ -65,6 +65,8 @@
#include "gstomx_tvp.h"
#include "gstomx_videomixer.h"
+#include "gstomxbufferalloc.h"
+
#include "config.h"
GST_DEBUG_CATEGORY (gstomx_debug);
@@ -86,7 +88,7 @@ static TableItem element_table[] =
{ "omx_mpeg4dec", "libOMX_Core.so", "OMX.TI.DUCATI.VIDDEC", "", GST_RANK_PRIMARY, gst_omx_mpeg4dec_get_type },
{ "omx_h264dec", "libOMX_Core.so", "OMX.TI.DUCATI.VIDDEC", "", GST_RANK_PRIMARY, gst_omx_h264dec_get_type },
{ "omx_mjpegdec", "libOMX_Core.so", "OMX.TI.DUCATI.VIDDEC", "", GST_RANK_PRIMARY, gst_omx_mjpegdec_get_type },
- { "omx_mpeg2dec", "libOMX_Core.so", "OMX.TI.DUCATI.VIDDEC", "", GST_RANK_PRIMARY, gst_omx_mpeg2dec_get_type },
+ { "omx_mpeg2dec", "libOMX_Core.so", "OMX.TI.DUCATI.VIDDEC", "", GST_RANK_PRIMARY - 1, gst_omx_mpeg2dec_get_type },
// { "omx_h263dec", "libOMX_Core.so", "OMX.TI.DUCATI.VIDDEC", "", GST_RANK_PRIMARY, gst_omx_h263dec_get_type },
// { "omx_vp6dec", "libOMX_Core.so", "OMX.TI.DUCATI1.VIDEO.DECODER", "video_decoder.vp6", GST_RANK_PRIMARY, gst_omx_vp6dec_get_type },
// { "omx_wmvdec", "libOMX_Core.so", "OMX.TI.Video.Decoder", NULL, GST_RANK_NONE, gst_omx_wmvdec_get_type },
@@ -101,8 +103,8 @@ static TableItem element_table[] =
// { "omx_amrnbenc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.amrnb", NULL, GST_RANK_NONE, gst_omx_amrnbenc_get_type },
// { "omx_amrwbdec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.amrwb", NULL, GST_RANK_NONE, gst_omx_amrwbdec_get_type },
// { "omx_amrwbenc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.amrwb", NULL, GST_RANK_NONE, gst_omx_amrwbenc_get_type },
- { "omx_aacdec", "libOMX_Core.so", "OMX.TI.DSP.AUDDEC", "", GST_RANK_PRIMARY, gst_omx_aacdec_get_type },
- { "omx_aacenc", "libOMX_Core.so", "OMX.TI.DSP.AUDENC", "", GST_RANK_PRIMARY, gst_omx_aacenc_get_type },
+ { "omx_aacdec", "libOMX_Core.so", "OMX.TI.DSP.AUDDEC", "", GST_RANK_NONE, gst_omx_aacdec_get_type },
+ { "omx_aacenc", "libOMX_Core.so", "OMX.TI.DSP.AUDENC", "", GST_RANK_NONE, gst_omx_aacenc_get_type },
// { "omx_adpcmdec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.adpcm", NULL, GST_RANK_NONE, gst_omx_adpcmdec_get_type },
// { "omx_adpcmenc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.adpcm", NULL, GST_RANK_NONE, gst_omx_adpcmenc_get_type },
// { "omx_g711dec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.g711", NULL, GST_RANK_NONE, gst_omx_g711dec_get_type },
@@ -114,16 +116,17 @@ static TableItem element_table[] =
// { "omx_jpegenc", "libOMX_Core.so", "OMX.TI.JPEG.encoder", NULL, GST_RANK_NONE, gst_omx_jpegenc_get_type },
// { "omx_jpegdec", "libOMX_Core.so", "OMX.TI.DUCATI1.IMAGE.JPEGD", NULL, GST_RANK_NONE, gst_omx_jpegdec_get_type },
// { "omx_audiosink", "libomxil-bellagio.so.0", "OMX.st.alsa.alsasink", NULL, GST_RANK_NONE, gst_omx_audiosink_get_type },
- { "omx_videosink", "libOMX_Core.so", "OMX.TI.VPSSM3.VFDC", NULL, GST_RANK_PRIMARY, gst_omx_videosink_get_type },
+ { "omx_videosink", "libOMX_Core.so", "OMX.TI.VPSSM3.VFDC", NULL, GST_RANK_NONE, gst_omx_videosink_get_type },
// { "omx_filereadersrc", "libomxil-bellagio.so.0", "OMX.st.audio_filereader", NULL, GST_RANK_NONE, gst_omx_filereadersrc_get_type },
// { "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 },
+ { "swcsc", "libOMX_Core.so", NULL, NULL, GST_RANK_NONE, 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 },
{ "omx_noisefilter", "libOMX_Core.so", "OMX.TI.VPSSM3.VFPC.NF", "", GST_RANK_PRIMARY, gst_omx_noisefilter_get_type },
- { "omx_ctrl", "libOMX_Core.so", "OMX.TI.VPSSM3.CTRL.DC", "", GST_RANK_PRIMARY, gst_omx_base_ctrl_get_type },
+ { "omx_ctrl", "libOMX_Core.so", "OMX.TI.VPSSM3.CTRL.DC", "", GST_RANK_NONE, gst_omx_base_ctrl_get_type },
{ "omx_tvp", "libOMX_Core.so", "OMX.TI.VPSSM3.CTRL.TVP", "", GST_RANK_PRIMARY, gst_omx_tvp_get_type },
{ "omx_camera", "libOMX_Core.so", "OMX.TI.VPSSM3.VFCC", NULL, GST_RANK_PRIMARY, gst_omx_camera_get_type },
{ "omx_videomixer", "libOMX_Core.so", "OMX.TI.VPSSM3.VFPC.INDTXSCWB", "", GST_RANK_PRIMARY, gst_omx_video_mixer_get_type },
View
18 omx/gstomx_base_filter.c
@@ -414,7 +414,7 @@ push_buffer (GstOmxBaseFilter *self,
PRINT_BUFFER (self, buf);
if (self->push_cb)
- self->push_cb (self);
+ self->push_cb (self, buf);
/** @todo check if tainted */
GST_LOG_OBJECT (self, "begin");
@@ -533,7 +533,17 @@ pad_chain (GstPad *pad,
//printf("INput!!\n");
PRINT_BUFFER (self, buf);
-
+ if(self->isFlushed == TRUE)
+ if(self->filterType == FILTER_DECODER) {
+ if(GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
+ gst_buffer_unref(buf);
+ return ret;
+ } else {
+ self->isFlushed = FALSE;
+ }
+ } else
+ self->isFlushed = FALSE;
+
gomx = self->gomx;
GST_LOG_OBJECT (self, "begin: size=%u, state=%d", GST_BUFFER_SIZE (buf), gomx->omx_state);
@@ -721,7 +731,7 @@ pad_event (GstPad *pad,
self->last_pad_push_return = GST_FLOW_OK;
g_omx_core_flush_stop (gomx);
-
+ self->isFlushed = TRUE;
if (self->ready)
gst_pad_start_task (self->srcpad, output_loop, self->srcpad);
@@ -885,6 +895,8 @@ type_instance_init (GTypeInstance *instance,
gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
+ self->isFlushed = FALSE;
+ self->filterType = FILTER_NONE;
self->duration = GST_CLOCK_TIME_NONE;
GST_LOG_OBJECT (self, "end");
View
12 omx/gstomx_base_filter.h
@@ -34,10 +34,18 @@ G_BEGIN_DECLS
typedef struct GstOmxBaseFilter GstOmxBaseFilter;
typedef struct GstOmxBaseFilterClass GstOmxBaseFilterClass;
typedef void (*GstOmxBaseFilterCb) (GstOmxBaseFilter *self);
+typedef void (*GstOmxBaseFilterPushCb) (GstOmxBaseFilter *self, GstBuffer *buf);
#include "gstomx_util.h"
#include <async_queue.h>
+typedef enum {
+ FILTER_NONE,
+ FILTER_DECODER,
+ FILTER_ENCODER,
+ FILTER_PP
+} filtertype;
+
struct GstOmxBaseFilter
{
GstElement element;
@@ -56,10 +64,12 @@ struct GstOmxBaseFilter
GMutex *ready_lock;
GstOmxBaseFilterCb omx_setup;
- GstOmxBaseFilterCb push_cb;
+ GstOmxBaseFilterPushCb push_cb;
GstFlowReturn last_pad_push_return;
GstBuffer *codec_data;
GstClockTime duration;
+ gboolean isFlushed;
+ guint filterType;
};
View
14 omx/gstomx_base_filter2.c
@@ -133,9 +133,15 @@ setup_input_buffer (GstOmxBaseFilter2 *self, GstBuffer *buf)
in_port = self->in_port;
in_port->share_buffer_info = malloc (sizeof(OmxBufferInfo));
if (self->input_fields_separately) {
+ int t1, t2;
+ t1 = GST_GET_OMXBUFFER(buf)->nOffset / param.format.video.nStride;
+ t2 = t1 + t1 + ((param.format.video.nFrameHeight + 7) & 0xFFFFFFF8);
+ t1 = t2 * param.format.video.nStride;
self->second_field_offset = ( GST_GET_OMXBUFFER(buf)->nFilledLen + GST_GET_OMXBUFFER(buf)->nOffset ) / 3;
- if (param.format.video.nFrameHeight & 7) {
- self->second_field_offset += (param.format.video.nStride * (8 - (param.format.video.nFrameHeight & 7)));
+ if (self->second_field_offset != t1) {
+ printf("Second field offset does not look right... correcting it from %d to %d\n",
+ self->second_field_offset, t1);
+ self->second_field_offset = t1;
}
in_port->share_buffer_info->pBuffer = malloc (sizeof(int) * port->num_buffers * 2);
for (i=0; i < port->num_buffers; i++) {
@@ -461,7 +467,7 @@ push_buffer (GstOmxBaseFilter2 *self,
PRINT_BUFFER (self, buf);
if (self->push_cb)
- self->push_cb (self);
+ self->push_cb (self, buf);
/** @todo check if tainted */
GST_LOG_OBJECT (self, "begin");
@@ -533,6 +539,8 @@ output_loop (gpointer data)
GstBuffer *buf = GST_BUFFER (obj);
ret = bclass->push_buffer (self, buf);
GST_DEBUG_OBJECT (self, "ret=%s", gst_flow_get_name (ret));
+ // HACK!! Dont care if one of the output pads are not connected
+ ret = GST_FLOW_OK;
}
}
else if (GST_IS_EVENT (obj))
View
3  omx/gstomx_base_filter2.h
@@ -34,6 +34,7 @@ G_BEGIN_DECLS
typedef struct GstOmxBaseFilter2 GstOmxBaseFilter2;
typedef struct GstOmxBaseFilter2Class GstOmxBaseFilter2Class;
typedef void (*GstOmxBaseFilter2Cb) (GstOmxBaseFilter2 *self);
+typedef void (*GstOmxBaseFilter2PushCb) (GstOmxBaseFilter2 *self, GstBuffer *buf);
#include "gstomx_util.h"
#include <async_queue.h>
@@ -58,7 +59,7 @@ struct GstOmxBaseFilter2
GMutex *ready_lock;
GstOmxBaseFilter2Cb omx_setup;
- GstOmxBaseFilter2Cb push_cb;
+ GstOmxBaseFilter2PushCb push_cb;
GstFlowReturn last_pad_push_return;
GstBuffer *codec_data;
GstClockTime duration;
View
37 omx/gstomx_base_videodec.c
@@ -21,11 +21,13 @@
#include "gstomx_base_videodec.h"
#include "gstomx.h"
+#include "gstomx_buffertransport.h"
#include <gst/video/video.h>
#ifdef USE_OMXTICORE
# include <OMX_TI_Index.h>
+# include <OMX_TI_Common.h>
#endif
#include <string.h> /* for memset */
@@ -145,9 +147,6 @@ sink_setcaps (GstPad *pad,
width, height);
return FALSE;
}
- if(width % 16)
- width = ((width/16) + 1)*16;
-
{
const GValue *framerate = NULL;
framerate = gst_structure_get_value (structure, "framerate");
@@ -466,6 +465,35 @@ omx_setup (GstOmxBaseFilter *omx_base)
GST_INFO_OBJECT (omx_base, "end");
}
+static void push_cb (GstOmxBaseFilter *omx_base, GstBuffer *buf)
+{
+ GstOmxBaseVideoDec *self;
+ OMX_BUFFERHEADERTYPE *omxbuffer;
+ GstCaps *caps, tmp;
+ GstStructure *structure;
+ gboolean i;
+
+ self = GST_OMX_BASE_VIDEODEC (omx_base);
+ omxbuffer = GST_GET_OMXBUFFER(buf);
+
+ /* Change interlaced flag in srcpad caps if decoder differs with
+ what is already got from the upstream element */
+ i = (0 != (omxbuffer->nFlags &
+ OMX_TI_BUFFERFLAG_VIDEO_FRAME_TYPE_INTERLACE));
+ if (i != self->interlaced) {
+ caps = gst_caps_copy(GST_PAD_CAPS(omx_base->srcpad));
+ self->interlaced = i;
+ structure = gst_caps_get_structure (caps, 0);
+ if (structure) {
+ gst_structure_set (structure,
+ "interlaced", G_TYPE_BOOLEAN, self->interlaced, NULL);
+ }
+ gst_pad_set_caps(omx_base->srcpad, caps);
+ if (GST_BUFFER_CAPS(buf)) gst_caps_unref(GST_BUFFER_CAPS(buf));
+ GST_BUFFER_CAPS(buf) = caps;
+ }
+}
+
static void
type_instance_init (GTypeInstance *instance,
gpointer g_class)
@@ -475,6 +503,7 @@ type_instance_init (GTypeInstance *instance,
omx_base = GST_OMX_BASE_FILTER (instance);
omx_base->omx_setup = omx_setup;
+ omx_base->push_cb = push_cb;
omx_base->gomx->settings_changed_cb = settings_changed_cb;
@@ -484,7 +513,7 @@ type_instance_init (GTypeInstance *instance,
omx_base->in_port->always_copy = TRUE;
omx_base->out_port->share_buffer = FALSE;
omx_base->out_port->always_copy = FALSE;
-
+ omx_base->filterType = FILTER_DECODER;
gst_pad_set_setcaps_function (omx_base->sinkpad,
GST_DEBUG_FUNCPTR (sink_setcaps));
View
60 omx/gstomx_buffertransport.c
@@ -98,13 +98,16 @@ release_buffer (GOmxPort *port, OMX_BUFFERHEADERTYPE *omx_buffer)
break;
}
}
+#include <sys/time.h>
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 ;
+}
View
2  omx/gstomx_buffertransport.h
@@ -61,6 +61,8 @@ struct _GstOmxBufferTransport {
GOmxPort *port;
guint numAdditionalHeaders;
OMX_BUFFERHEADERTYPE **addHeader;
+ GstBuffer *parent;
+ GSem *bufSem;
};
struct _GstOmxBufferTransportClass {
View
81 omx/gstomx_deiscaler.c
@@ -121,6 +121,8 @@ create_src_caps (GstOmxBaseFilter2 *omx_base, int idx)
} else
gst_structure_get_int (s, "rowstride", &rowstride);
}
+ /* Workaround: Make width multiple of 16, otherwise, scaler crashes */
+ width = (width+15) & 0xFFFFFFF0;
if (caps) gst_caps_unref (caps);
@@ -182,6 +184,18 @@ omx_setup (GstOmxBaseFilter2 *omx_base)
GST_LOG_OBJECT (self, "begin");
+ omx_base->input_fields_separately = self->interlaced;
+
+ if (omx_base->duration != GST_CLOCK_TIME_NONE) {
+ omx_base->duration *= (GST_OMX_DEISCALER(self))->framerate_divisor;
+ self->framerate_denom *= (GST_OMX_DEISCALER(self))->framerate_divisor;
+ if (omx_base->input_fields_separately) {
+ // Halve the duration of output frame
+ omx_base->duration = omx_base->duration/2;
+ self->framerate_num *= 2;
+ }
+ }
+
/* set the output cap */
for (i=0 ; i<NUM_OUTPUTS; i++)
gst_pad_set_caps (omx_base->srcpad[i], create_src_caps (omx_base, i));
@@ -258,9 +272,6 @@ omx_setup (GstOmxBaseFilter2 *omx_base)
/* Set input channel resolution */
GST_LOG_OBJECT (self, "Setting channel resolution (input)");
- x = 0; // self->in_stride % self->in_width;
- y = 0; // self->in_stride / self->in_width;
-
_G_OMX_INIT_PARAM (&chResolution);
chResolution.Frm0Width = self->in_width;
chResolution.Frm0Height = self->in_height >> shift;
@@ -270,8 +281,8 @@ omx_setup (GstOmxBaseFilter2 *omx_base)
chResolution.Frm1Pitch = 0;
chResolution.FrmStartX = x;
chResolution.FrmStartY = y;
- chResolution.FrmCropWidth = self->in_width - x;
- chResolution.FrmCropHeight = (self->in_height - y) >> shift;
+ chResolution.FrmCropWidth = self->in_width;
+ chResolution.FrmCropHeight = self->in_height >> shift;
chResolution.eDir = OMX_DirInput;
chResolution.nChId = 0;
err = OMX_SetConfig (gomx->omx_handle, OMX_TI_IndexConfigVidChResolution, &chResolution);
@@ -281,7 +292,7 @@ omx_setup (GstOmxBaseFilter2 *omx_base)
#if 1
_G_OMX_INIT_PARAM(&sSubSamplinginfo);
- sSubSamplinginfo.nSubSamplingFactor = 1;
+ sSubSamplinginfo.nSubSamplingFactor = (GST_OMX_DEISCALER(self))->framerate_divisor;
err = OMX_SetConfig ( gomx->omx_handle, ( OMX_INDEXTYPE )
( OMX_TI_IndexConfigSubSamplingFactor ),
&sSubSamplinginfo );
@@ -315,23 +326,66 @@ omx_setup (GstOmxBaseFilter2 *omx_base)
algEnable.nChId = 0;
algEnable.bAlgBypass = (self->interlaced)?OMX_FALSE:OMX_TRUE;
- omx_base->input_fields_separately = self->interlaced;
- if (omx_base->input_fields_separately) {
- // Halve the duration of output frame
- if (omx_base->duration != GST_CLOCK_TIME_NONE)
- omx_base->duration /= 2;
- }
-
err = OMX_SetConfig (gomx->omx_handle, (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgEnable, &algEnable);
if (err != OMX_ErrorNone)
return;
}
+enum
+{
+ ARG_0,
+ ARG_FRAMERATE_DIV,
+};
+
+static void
+set_property (GObject *obj,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case ARG_FRAMERATE_DIV:
+ (GST_OMX_DEISCALER(obj))->framerate_divisor = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+get_property (GObject *obj,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case ARG_FRAMERATE_DIV:
+ g_value_set_uint (value, (GST_OMX_DEISCALER(obj))->framerate_divisor);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
static void
type_class_init (gpointer g_class,
gpointer class_data)
{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (g_class);
+ gobject_class->set_property = set_property;
+ gobject_class->get_property = get_property;
+
+ g_object_class_install_property (gobject_class, ARG_FRAMERATE_DIV,
+ g_param_spec_uint ("framerate-divisor", "Output framerate divisor",
+ "Output framerate = (2 * input_framerate) / framerate_divisor",
+ 1, 60, 1, G_PARAM_READWRITE));
}
static void
@@ -344,5 +398,6 @@ type_instance_init (GTypeInstance *instance,
self->omx_setup = omx_setup;
+ (GST_OMX_DEISCALER(instance))->framerate_divisor = 1;
}
View
3  omx/gstomx_deiscaler.h
@@ -26,7 +26,7 @@
G_BEGIN_DECLS
-// #define GST_OMX_DEISCALER(obj) (GstOmxDeiScaler *) (obj)
+#define GST_OMX_DEISCALER(obj) (struct GstOmxDeiScaler *) (obj)
// #define GST_OMX_DEISCALER_TYPE (gst_omx_deiscaler_get_type ())
typedef struct GstOmxDeiScaler GstOmxMDeiScaler;
@@ -39,6 +39,7 @@ typedef struct GstOmxDeiScalerClass GstOmxHDeiScalerClass;
struct GstOmxDeiScaler
{
GstOmxBaseVfpc2 omx_base;
+ gint framerate_divisor;
};
struct GstOmxDeiScalerClass
View
250 omx/gstomx_h264enc.c
@@ -24,6 +24,8 @@
#include "gstomx_h264enc.h"
#include "gstomx.h"
+#include <OMX_TI_Index.h>
+#include <OMX_TI_Video.h>
#include <string.h> /* for memset */
@@ -38,11 +40,15 @@ enum
ARG_I_PERIOD,
ARG_IDR_PERIOD,
ARG_FORCE_IDR,
+ ARG_ENCODING_PRESET,
+ ARG_RATECONTROL_PRESET,
};
#define DEFAULT_BYTESTREAM FALSE
-#define DEFAULT_PROFILE OMX_VIDEO_AVCProfileHigh
-#define DEFAULT_LEVEL OMX_VIDEO_AVCLevel4
+#define DEFAULT_PROFILE OMX_VIDEO_AVCProfileBaseline
+#define DEFAULT_LEVEL OMX_VIDEO_AVCLevel42
+#define DEFAULT_ENCODE_PRESET OMX_Video_Enc_High_Speed_Med_Quality
+#define DEFAULT_RATECONTROL_PRESET OMX_Video_RC_Low_Delay
#define GST_TYPE_OMX_VIDEO_AVCPROFILETYPE (gst_omx_video_avcprofiletype_get_type ())
static GType
@@ -105,6 +111,54 @@ gst_omx_video_avcleveltype_get_type ()
return type;
}
+#define GST_TYPE_OMX_VIDEO_ENCODE_PRESETTYPE (gst_omx_video_enocdepreset_get_type ())
+static GType
+gst_omx_video_enocdepreset_get_type ()
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GEnumValue vals[] =
+ {
+ {OMX_Video_Enc_High_Quality, "High Quality", "hq"},
+ {OMX_Video_Enc_User_Defined, "User Defined", "user"},
+ {OMX_Video_Enc_High_Speed_Med_Quality, "High Speed Med Qual", "hsmq"},
+ {OMX_Video_Enc_Med_Speed_Med_Quality, "Med Speed Med Qaul", "msmq"},
+ {OMX_Video_Enc_Med_Speed_High_Quality, "Med Speed High Qaul", "mshq"},
+ {OMX_Video_Enc_High_Speed, "High Speed", "hs"},
+ {0, NULL, NULL },
+ };
+
+ type = g_enum_register_static ("GstOmxVideoEncoderPreset", vals);
+ }
+
+ return type;
+}
+
+#define GST_TYPE_OMX_VIDEO_RATECONTROL_PRESETTYPE (gst_omx_video_ratecontrolpreset_get_type ())
+static GType
+gst_omx_video_ratecontrolpreset_get_type ()
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GEnumValue vals[] =
+ {
+ {OMX_Video_RC_Low_Delay, "Low Delay", "low-delay"},
+ {OMX_Video_RC_Storage, "Storage", "storage"},
+ {OMX_Video_RC_Twopass, "Two Pass", "two-pass"},
+ {OMX_Video_RC_None, "none", "none"},
+ {0, NULL, NULL },
+ };
+
+ type = g_enum_register_static ("GstOmxVideoRateControlPreset", vals);
+ }
+
+ return type;
+}
+
static GstCaps *
generate_src_template (void)
{
@@ -114,6 +168,8 @@ generate_src_template (void)
"width", GST_TYPE_INT_RANGE, 16, 4096,
"height", GST_TYPE_INT_RANGE, 16, 4096,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,
+ "stream-format", G_TYPE_STRING, "byte-stream",
+ "alignment", G_TYPE_STRING, "au",
NULL);
return caps;
@@ -166,6 +222,7 @@ set_property (GObject *obj,
self->bytestream = g_value_get_boolean (value);
break;
case ARG_PROFILE:
+ #if 0
{
OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel;
OMX_ERRORTYPE error_val = OMX_ErrorNone;
@@ -186,7 +243,12 @@ set_property (GObject *obj,
g_assert (error_val == OMX_ErrorNone);
break;
}
+ #else
+ self->profile = g_value_get_enum(value);
+ break;
+ #endif
case ARG_LEVEL:
+ #if 0
{
OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel;
OMX_ERRORTYPE error_val = OMX_ErrorNone;
@@ -207,7 +269,12 @@ set_property (GObject *obj,
g_assert (error_val == OMX_ErrorNone);
break;
}
+ #else
+ self->level = g_value_get_enum(value);
+ break;
+ #endif
case ARG_I_PERIOD:
+ #if 0
{
OMX_VIDEO_CONFIG_AVCINTRAPERIOD avcIntraPeriod;
OMX_ERRORTYPE error_val = OMX_ErrorNone;
@@ -229,6 +296,10 @@ set_property (GObject *obj,
g_assert (error_val == OMX_ErrorNone);
break;
}
+ #else
+ self->i_period = g_value_get_uint (value);
+ break;
+ #endif
case ARG_IDR_PERIOD:
{
self->idr_period = g_value_get_uint (value);
@@ -239,6 +310,54 @@ set_property (GObject *obj,
self->force_idr = g_value_get_boolean (value);
break;
}
+ case ARG_ENCODING_PRESET:
+ {
+ #if 0
+ OMX_ERRORTYPE error_val = OMX_ErrorNone;
+ OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset;
+ _G_OMX_INIT_PARAM(&tEncoderPreset);
+ tEncoderPreset.nPortIndex = omx_base->out_port->port_index;
+
+ error_val =
+ OMX_GetParameter(g_omx_core_get_handle (omx_base->gomx),
+ OMX_TI_IndexParamVideoEncoderPreset,
+ &tEncoderPreset);
+ g_assert (error_val == OMX_ErrorNone);
+
+ tEncoderPreset.eEncodingModePreset = g_value_get_enum (value);
+ error_val = OMX_SetParameter(g_omx_core_get_handle (omx_base->gomx),
+ OMX_TI_IndexParamVideoEncoderPreset,
+ &tEncoderPreset);
+ g_assert (error_val == OMX_ErrorNone);
+ #else
+ self->encodingPreset = g_value_get_enum(value);
+ #endif
+ break;
+ }
+ case ARG_RATECONTROL_PRESET:
+ {
+ #if 0
+ OMX_ERRORTYPE error_val = OMX_ErrorNone;
+ OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset;
+ _G_OMX_INIT_PARAM(&tEncoderPreset);
+ tEncoderPreset.nPortIndex = omx_base->out_port->port_index;
+
+ error_val =
+ OMX_GetParameter(g_omx_core_get_handle (omx_base->gomx),
+ OMX_TI_IndexParamVideoEncoderPreset,
+ &tEncoderPreset);
+ g_assert (error_val == OMX_ErrorNone);
+
+ tEncoderPreset.eRateControlPreset = g_value_get_enum (value);
+ error_val = OMX_SetParameter(g_omx_core_get_handle (omx_base->gomx),
+ OMX_TI_IndexParamVideoEncoderPreset,
+ &tEncoderPreset);
+ g_assert (error_val == OMX_ErrorNone);
+ #else
+ self->ratecontrolPreset = g_value_get_enum(value);
+ #endif
+ break;
+ }
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@@ -263,6 +382,7 @@ get_property (GObject *obj,
g_value_set_boolean (value, self->bytestream);
break;
case ARG_PROFILE:
+ #if 0
{
OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel;
GOmxCore *gomx;
@@ -282,7 +402,12 @@ get_property (GObject *obj,
break;
}
+ #else
+ g_value_set_enum(value, self->profile);
+ break;
+ #endif
case ARG_LEVEL:
+ #if 0
{
OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel;
GOmxCore *gomx;
@@ -302,7 +427,12 @@ get_property (GObject *obj,
break;
}
+ #else
+ g_value_set_enum(value, self->level);
+ break;
+ #endif
case ARG_I_PERIOD:
+ #if 0
{
OMX_VIDEO_CONFIG_AVCINTRAPERIOD avcIntraPeriod;
GOmxCore *gomx;
@@ -317,6 +447,10 @@ get_property (GObject *obj,
break;
}
+ #else
+ g_value_set_uint(value, self->i_period);
+ break;
+ #endif
case ARG_IDR_PERIOD:
{
g_value_set_uint (value, self->idr_period);
@@ -329,6 +463,46 @@ get_property (GObject *obj,
break;
}
+ case ARG_ENCODING_PRESET:
+ {
+ #if 0
+ OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset;
+ GOmxCore *gomx;
+ OMX_ERRORTYPE error_val = OMX_ErrorNone;
+
+ gomx = (GOmxCore *) omx_base->gomx;
+ error_val = OMX_GetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset,
+ &tEncoderPreset);
+
+ g_value_set_enum (value, tEncoderPreset.eEncodingModePreset);
+
+ GST_DEBUG_OBJECT (self, "Encoding Preset: param=%d",
+ (gint)tEncoderPreset.eEncodingModePreset);
+ #else
+ g_value_set_enum(value, self->encodingPreset);
+ #endif
+ break;
+ }
+ case ARG_RATECONTROL_PRESET:
+ {
+ #if 0
+ OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset;
+ GOmxCore *gomx;
+ OMX_ERRORTYPE error_val = OMX_ErrorNone;
+
+ gomx = (GOmxCore *) omx_base->gomx;
+ error_val = OMX_GetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset,
+ &tEncoderPreset);
+
+ g_value_set_enum (value, tEncoderPreset.eRateControlPreset);
+
+ GST_DEBUG_OBJECT (self, "RateControl Preset: param=%d",
+ (gint)tEncoderPreset.eRateControlPreset);
+ #else
+ g_value_set_enum(value, self->ratecontrolPreset);
+ #endif
+ break;
+ }
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@@ -366,7 +540,7 @@ type_class_init (gpointer g_class,
g_object_class_install_property (gobject_class, ARG_I_PERIOD,
g_param_spec_uint ("i-period", "Specifies periodicity of I frames",
"Specifies periodicity of I frames (0:Disable)",
- 0, G_MAXINT32, 0, G_PARAM_READWRITE));
+ 0, G_MAXINT32, 90, G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, ARG_IDR_PERIOD,
g_param_spec_uint ("force-idr-period", "Specifies periodicity of IDR frames",
"Specifies periodicity of IDR frames (0:Disable)",
@@ -374,15 +548,25 @@ type_class_init (gpointer g_class,
g_object_class_install_property (gobject_class, ARG_FORCE_IDR,
g_param_spec_boolean ("force-idr", "force-idr", "force next frame to be IDR",
FALSE, G_PARAM_WRITABLE));
-
+ g_object_class_install_property (gobject_class, ARG_ENCODING_PRESET,
+ g_param_spec_enum ("encodingPreset", "Specifies which encoding preset to use",
+ "Specifies which encoding preset to use",
+ GST_TYPE_OMX_VIDEO_ENCODE_PRESETTYPE,
+ DEFAULT_ENCODE_PRESET,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_RATECONTROL_PRESET,
+ g_param_spec_enum ("rateControlPreset", "Specifies what rate control preset to use",
+ "Specifies what rate control preset to use",
+ GST_TYPE_OMX_VIDEO_RATECONTROL_PRESETTYPE,
+ DEFAULT_RATECONTROL_PRESET,
+ G_PARAM_READWRITE));
}
}
static void
-omx_h264_push_cb (GstOmxBaseFilter *omx_base)
+omx_h264_push_cb (GstOmxBaseFilter *omx_base, GstBuffer *buf)
{
- static guint cont;
GstOmxH264Enc *self;
self = GST_OMX_H264ENC (omx_base);
@@ -391,7 +575,7 @@ omx_h264_push_cb (GstOmxBaseFilter *omx_base)
*/
if ((self->idr_period > 0) || (self->force_idr))
{
- if ((cont == self->idr_period) || (self->force_idr))
+ if ((self->cont == self->idr_period) || (self->force_idr))
{
OMX_CONFIG_INTRAREFRESHVOPTYPE confIntraRefreshVOP;
@@ -407,19 +591,19 @@ omx_h264_push_cb (GstOmxBaseFilter *omx_base)
OMX_IndexConfigVideoIntraVOPRefresh,
&confIntraRefreshVOP);
- if (cont == self->idr_period)
- cont = 0;
+ if (self->cont == self->idr_period)
+ self->cont = 0;
if (self->force_idr)
{
self->force_idr = FALSE;
- cont++;
+ self->cont++;
}
} else {
- cont++;
+ self->cont++;
}
}
-
+ GST_BUFFER_CAPS(buf) = gst_caps_ref(GST_PAD_CAPS(omx_base->srcpad));
}
static void
@@ -427,7 +611,9 @@ omx_setup (GstOmxBaseFilter *omx_base)
{
GstOmxBaseVideoEnc *self;
GOmxCore *gomx;
+ GstOmxH264Enc *h264enc;
+ h264enc = GST_OMX_H264ENC (omx_base);
self = GST_OMX_BASE_VIDEOENC (omx_base);
gomx = (GOmxCore *) omx_base->gomx;
@@ -439,9 +625,7 @@ omx_setup (GstOmxBaseFilter *omx_base)
if (OMX_GetExtensionIndex (gomx->omx_handle, "OMX.TI.VideoEncode.Config.NALFormat", &index) == OMX_ErrorNone)
{
OMX_U32 nal_format;
- GstOmxH264Enc *h264enc;
- h264enc = GST_OMX_H264ENC (omx_base);
nal_format = h264enc->bytestream ? 0 : 1;
GST_DEBUG_OBJECT (omx_base, "setting 'OMX.TI.VideoEncode.Config.NALFormat' to %ld", nal_format);
@@ -452,6 +636,35 @@ omx_setup (GstOmxBaseFilter *omx_base)
GST_WARNING_OBJECT (omx_base, "'OMX.TI.VideoEncode.Config.NALFormat' unsupported");
}
}
+ {
+ OMX_VIDEO_PARAM_AVCTYPE tAVCParams;
+
+ _G_OMX_INIT_PARAM (&tAVCParams);
+
+ tAVCParams.nPortIndex = OMX_DirOutput;
+ OMX_GetParameter(gomx->omx_handle, OMX_IndexParamVideoAvc, &tAVCParams);
+
+ tAVCParams.eLevel = h264enc->level;
+ tAVCParams.eProfile = h264enc->profile;
+ tAVCParams.nPFrames = h264enc->i_period - 1;
+ tAVCParams.nBFrames = 0;
+
+ OMX_SetParameter(gomx->omx_handle, OMX_IndexParamVideoAvc, &tAVCParams);
+ }
+
+ {
+ OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset;
+
+ _G_OMX_INIT_PARAM(&tEncoderPreset);
+ tEncoderPreset.nPortIndex = omx_base->out_port->port_index;
+
+ OMX_GetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset, &tEncoderPreset);
+
+ tEncoderPreset.eEncodingModePreset = h264enc->encodingPreset;
+ tEncoderPreset.eRateControlPreset = h264enc->ratecontrolPreset;
+
+ OMX_SetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset, &tEncoderPreset);
+ }
GST_INFO_OBJECT (omx_base, "end");
}
@@ -485,6 +698,8 @@ settings_changed_cb (GOmxCore *core)
"height", G_TYPE_INT, height,
"framerate", GST_TYPE_FRACTION,
omx_base->framerate_num, omx_base->framerate_denom,
+ "stream-format", G_TYPE_STRING, "byte-stream",
+ "alignment", G_TYPE_STRING, "au",
NULL);
GST_INFO_OBJECT (omx_base, "caps are: %" GST_PTR_FORMAT, new_caps);
@@ -515,5 +730,12 @@ type_instance_init (GTypeInstance *instance,
omx_base_filter->gomx->settings_changed_cb = settings_changed_cb;
self->idr_period = 0;
+ self->cont = 0;
self->force_idr = FALSE;
+
+ self->i_period = 90;
+ self->profile = DEFAULT_PROFILE;
+ self->level = DEFAULT_LEVEL;
+ self->encodingPreset = OMX_Video_Enc_High_Speed_Med_Quality;
+ self->ratecontrolPreset = OMX_Video_RC_Low_Delay;
}
View
6 omx/gstomx_h264enc.h
@@ -40,6 +40,12 @@ struct GstOmxH264Enc
gboolean bytestream;
gint idr_period;
gint force_idr;
+ OMX_VIDEO_AVCPROFILETYPE profile;
+ OMX_VIDEO_AVCLEVELTYPE level;
+ gint i_period;
+ OMX_VIDEO_ENCODING_MODE_PRESETTYPE encodingPreset;
+ OMX_VIDEO_RATECONTROL_PRESETTYPE ratecontrolPreset;
+ gint cont;
};
struct GstOmxH264EncClass
View
20 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);
@@ -1089,7 +1099,7 @@ g_omx_port_flush (GOmxPort *port)
{
omx_buffer->nFilledLen = 0;
-#ifdef USE_OMXTICORE
+#if 0
if (omx_buffer->nFlags & OMX_TI_BUFFERFLAG_READONLY)
{
/* For output buffer that is marked with READONLY, we
View
4 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. */
View
10 omx/gstomx_scaler.c
@@ -93,6 +93,8 @@ create_src_caps (GstOmxBaseFilter *omx_base)
height = self->in_height;
}
}
+ /* Workaround: Make width multiple of 16, otherwise, scaler crashes */
+ width = (width+15) & 0xFFFFFFF0;
caps = gst_caps_new_empty ();
struc = gst_structure_new (("video/x-raw-yuv"),
@@ -218,10 +220,10 @@ omx_setup (GstOmxBaseFilter *omx_base)
chResolution.Frm1Width = 0;
chResolution.Frm1Height = 0;
chResolution.Frm1Pitch = 0;
- chResolution.FrmStartX = 0;//self->left;
- chResolution.FrmStartY = 0;//self->top;
- chResolution.FrmCropWidth = 0;//self->in_width - self->left;
- chResolution.FrmCropHeight = 0;//self->in_height - self->top;
+ chResolution.FrmStartX = 0;
+ chResolution.FrmStartY = 0;
+ chResolution.FrmCropWidth = 0;
+ chResolution.FrmCropHeight = 0;
chResolution.eDir = OMX_DirInput;
chResolution.nChId = 0;
err = OMX_SetConfig (gomx->omx_handle, OMX_TI_IndexConfigVidChResolution, &chResolution);
View
5 omx/gstomx_vc1dec.c
@@ -37,6 +37,7 @@ generate_sink_template (void)
caps = gst_caps_new_empty ();
struc = gst_structure_new ("video/x-wmv",
+ "wmvversion", G_TYPE_INT, 3,
"width", GST_TYPE_INT_RANGE, 16, 4096,
"height", GST_TYPE_INT_RANGE, 16, 4096,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,
@@ -47,6 +48,7 @@ generate_sink_template (void)
return caps;
}
+#if 0 // SRC pad template already exists in gstomx_base_videodec.c
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE(
"src",
GST_PAD_SRC,
@@ -59,6 +61,7 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE(
"height=(int)[ 1, MAX ]"
)
);
+#endif
static void
type_base_init (gpointer g_class)
@@ -87,8 +90,10 @@ type_base_init (gpointer g_class)
gst_element_class_add_pad_template (element_class, template);
+#if 0
gst_element_class_add_pad_template(element_class,
gst_static_pad_template_get (&src_factory));
+#endif
}
}
View
400 omx/gstomx_videomixer.c
@@ -34,6 +34,18 @@ enum
ARG_NUM_INPUT_BUFFERS,
ARG_NUM_OUTPUT_BUFFERS,
ARG_PORT_INDEX,
+ ARG_FRAME_RATE,
+ ARG_SETTINGS_CHANGED
+};
+
+enum
+{
+ ARG_00,
+ ARG_OUT_WIDTH,
+ ARG_OUT_HEIGHT,
+ ARG_OUT_X,
+ ARG_OUT_Y,
+ ARG_OUT_ZORDER
};
static void init_interfaces (GType type);
@@ -61,6 +73,109 @@ static GstFlowReturn pad_chain (GstPad *pad, GstBuffer *buf);
static gboolean pad_event (GstPad *pad, GstEvent *event);
static void* vidmix_input_loop(void *arg);
+static void gst_videomixer_pad_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static void gst_videomixer_pad_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+
+
+GType gst_videomixer_pad_get_type (void);
+G_DEFINE_TYPE (GstVideoMixerPad, gst_videomixer_pad, GST_TYPE_PAD);
+
+static void
+gst_videomixer_pad_class_init (GstVideoMixerPadClass * klass)
+{
+
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ printf("pad class init!!\n");
+ gobject_class->set_property = gst_videomixer_pad_set_property;
+ gobject_class->get_property = gst_videomixer_pad_get_property;
+
+ g_object_class_install_property (gobject_class, ARG_OUT_WIDTH,
+ g_param_spec_uint ("outWidth", "Output width",
+ "Op width",
+ 0, 100000, 0, G_PARAM_WRITABLE));
+
+ g_object_class_install_property (gobject_class, ARG_OUT_HEIGHT,
+ g_param_spec_uint ("outHeight", "Output height",
+ "op height",
+ 0, 100000, 0, G_PARAM_WRITABLE));
+
+ g_object_class_install_property (gobject_class, ARG_OUT_X,
+ g_param_spec_uint ("outX", "Output X",
+ "op X",
+ 0, 100000, 0, G_PARAM_WRITABLE));
+
+ g_object_class_install_property (gobject_class, ARG_OUT_Y,
+ g_param_spec_uint ("outY", "Output Y",
+ "op Y",
+ 0, 100000, 0, G_PARAM_WRITABLE));
+
+ g_object_class_install_property (gobject_class, ARG_OUT_ZORDER,
+ g_param_spec_uint ("zorder", "Z-Order", "Z Order of the picture",
+ 0, 10000, 0,
+ G_PARAM_WRITABLE));
+
+}
+
+static void
+gst_videomixer_pad_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstVideoMixerPad *pad = GST_VIDEO_MIXER_PAD (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_videomixer_pad_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstVideoMixerPad *pad = GST_VIDEO_MIXER_PAD (object);
+ ip_params *ch_info;
+ ch_info = (ip_params *)gst_pad_get_element_private(pad);
+ switch (prop_id) {
+ case ARG_OUT_WIDTH:
+ ch_info->outWidth = g_value_get_uint (value);
+ break;
+ case ARG_OUT_HEIGHT:
+ ch_info->outHeight = g_value_get_uint (value);
+ break;
+ case ARG_OUT_X:
+ ch_info->outX = g_value_get_uint (value);
+ break;
+ case ARG_OUT_Y:
+ ch_info->outY = g_value_get_uint (value);
+ break;
+ case ARG_OUT_ZORDER:
+ ch_info->order = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_videomixer_pad_init (GstVideoMixerPad * mixerpad)
+{
+/*
+ gst_pad_set_setcaps_function (GST_PAD (mixerpad),
+ gst_videomixer_pad_sink_setcaps);
+ gst_pad_set_acceptcaps_function (GST_PAD (mixerpad),
+ GST_DEBUG_FUNCPTR (gst_videomixer_pad_sink_acceptcaps));
+ gst_pad_set_getcaps_function (GST_PAD (mixerpad),
+ gst_videomixer_pad_sink_getcaps);
+
+ mixerpad->zorder = DEFAULT_PAD_ZORDER;
+ mixerpad->xpos = DEFAULT_PAD_XPOS;
+ mixerpad->ypos = DEFAULT_PAD_YPOS;
+ mixerpad->alpha = DEFAULT_PAD_ALPHA;*/
+}
static void
@@ -191,10 +306,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++)
@@ -205,6 +322,10 @@ change_state (GstElement *element,
g_omx_core_stop (core);
g_omx_core_unload (core);
+ for(ii = 0; ii < NUM_PORTS; ii++)
+ g_free(self->orderList[ii]);
+
+ g_free(self->orderList);
self->ready = FALSE;
}
// g_mutex_unlock (self->ready_lock);
@@ -251,10 +372,66 @@ finalize (GObject *obj)
g_free (self->omx_library);
g_mutex_free (self->ready_lock);
+ g_mutex_free (self->loop_lock);
G_OBJECT_CLASS (parent_class)->finalize (obj);
}
+void update_scaler(GstOmxVideoMixer *self)
+{
+ GOmxCore *gomx;
+ OMX_ERRORTYPE err;
+ int ii,kk;
+ Olist tmp;
+
+ OMX_CONFIG_VIDCHANNEL_RESOLUTION chResolution;
+ gomx = (GOmxCore *) self->gomx;
+
+ g_mutex_lock(self->loop_lock);
+ /* Set output channel resolution */
+ GST_LOG_OBJECT (self, "Setting channel resolution (output)");
+ for(ii = 0;ii < NUM_PORTS ; ii++) {
+ _G_OMX_INIT_PARAM (&chResolution);
+ chResolution.Frm0Width = self->chInfo[ii].outWidth;
+ chResolution.Frm0Height = self->chInfo[ii].outHeight;
+ chResolution.Frm0Pitch = self->out_stride;
+ chResolution.Frm1Width = 0;
+ chResolution.Frm1Height = 0;
+ chResolution.Frm1Pitch = 0;
+ chResolution.FrmStartX = self->chInfo[ii].outX*2;
+ chResolution.FrmStartY = self->chInfo[ii].outY;
+ chResolution.FrmCropWidth = 0;
+ chResolution.FrmCropHeight = 0;
+ chResolution.eDir = OMX_DirOutput;
+ chResolution.nPortIndex = ii;
+ chResolution.nChId = ii;
+ //printf("calling setconfig!!\n");
+ err = OMX_SetConfig (gomx->omx_handle, OMX_TI_IndexConfigVidChResolution, &chResolution);
+
+ if (err != OMX_ErrorNone) {
+ printf("error setting param!!\n");
+ return;
+ }
+ self->orderList[ii]->idx = ii;
+ self->orderList[ii]->order = self->chInfo[ii].order;
+ }
+
+
+ for(ii=0;ii<NUM_PORTS;ii++)
+ for(kk=ii+1;kk<NUM_PORTS;kk++)
+ if(self->orderList[kk]->order < self->orderList[ii]->order) {
+ tmp = *(self->orderList[kk]);
+ *(self->orderList[kk]) = *(self->orderList[ii]);
+ *(self->orderList[ii]) = tmp;
+ }
+ printf("ip zorder - starting from lowest: %d",self->orderList[0]->idx);
+ for(ii=1;ii<NUM_PORTS;ii++)
+ printf(", %d",self->orderList[ii]->idx);
+ printf("\n");
+ g_mutex_unlock(self->loop_lock);
+ //printf("Ret!!\n");
+
+}
static void
set_property (GObject *obj,
guint prop_id,
@@ -303,6 +480,14 @@ 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;
+ case ARG_SETTINGS_CHANGED:
+ self->settingsChanged = g_value_get_boolean (value);
+ update_scaler(self);
+ printf("settings updated!!\n");
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@@ -338,7 +523,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, &param);
@@ -438,7 +623,20 @@ 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));
+
+ g_object_class_install_property (gobject_class, ARG_SETTINGS_CHANGED,
+ g_param_spec_boolean ("settingsChanged", "settingsChanged",
+ "Indicate if the port settings have changed",
+ TRUE, G_PARAM_WRITABLE));
}
+
+ /* Register the pad class */
+ (void) (GST_TYPE_VIDEO_MIXER_PAD);
}
static GstCaps*
@@ -451,10 +649,12 @@ create_src_caps (GstOmxVideoMixer *omx_base)
self = GST_OMX_VIDEO_MIXER (omx_base);
caps = gst_pad_peer_get_caps (omx_base->srcpad);
+
if (gst_caps_is_empty (caps))
{
width = self->chInfo[0].in_width;
height = self->chInfo[0].in_height;
+
}
else
{
@@ -467,8 +667,10 @@ create_src_caps (GstOmxVideoMixer *omx_base)
{
width = self->chInfo[0].in_width;
height = self->chInfo[0].in_height;
+
}
}
+
caps = gst_caps_new_empty ();
struc = gst_structure_new (("video/x-raw-yuv"),
"width", G_TYPE_INT, width,
@@ -485,10 +687,10 @@ create_src_caps (GstOmxVideoMixer *omx_base)
gst_caps_append_structure (caps, struc);
-
return caps;
}
+guint arr[4][2] = { {0,0}, {1,0}, {0,1}, {1,1} };
static void
scaler_setup (GstOmxVideoMixer *omx_base)
@@ -507,6 +709,7 @@ scaler_setup (GstOmxVideoMixer *omx_base)
self = GST_OMX_VIDEO_MIXER (omx_base);
GST_LOG_OBJECT (self, "begin");
+
/* set the output cap */
gst_pad_set_caps (omx_base->srcpad, create_src_caps (omx_base));
@@ -552,8 +755,8 @@ scaler_setup (GstOmxVideoMixer *omx_base)
GST_LOG_OBJECT (self, "Setting port definition (output)");
G_OMX_PORT_GET_DEFINITION (omx_base->out_port[ii], &paramPort);
- paramPort.format.video.nFrameWidth = self->out_width/2;
- paramPort.format.video.nFrameHeight = self->out_height/2;
+ paramPort.format.video.nFrameWidth = self->out_width;
+ paramPort.format.video.nFrameHeight = self->out_height;
paramPort.format.video.nStride = self->out_stride;
paramPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
paramPort.format.video.eColorFormat = OMX_COLOR_FormatYCbYCr;
@@ -602,14 +805,15 @@ scaler_setup (GstOmxVideoMixer *omx_base)
/* Set output channel resolution */
GST_LOG_OBJECT (self, "Setting channel resolution (output)");
_G_OMX_INIT_PARAM (&chResolution);
- chResolution.Frm0Width = self->out_width/2;
- chResolution.Frm0Height = self->out_height/2;
+
+ chResolution.Frm0Width = self->out_width/2;
+ chResolution.Frm0Height = self->out_height/2;
chResolution.Frm0Pitch = self->out_stride;
chResolution.Frm1Width = 0;
chResolution.Frm1Height = 0;
chResolution.Frm1Pitch = 0;
- chResolution.FrmStartX = 0;
- chResolution.FrmStartY = 0;
+ chResolution.FrmStartX = arr[ii][0]*(chResolution.Frm0Width*2);
+ chResolution.FrmStartY = arr[ii][1]*chResolution.Frm0Height;
chResolution.FrmCropWidth = 0;
chResolution.FrmCropHeight = 0;
chResolution.eDir = OMX_DirOutput;
@@ -620,6 +824,11 @@ scaler_setup (GstOmxVideoMixer *omx_base)
if (err != OMX_ErrorNone)
return;
+ self->chInfo[ii].outWidth = chResolution.Frm0Width;
+ self->chInfo[ii].outHeight = chResolution.Frm0Height;
+ self->chInfo[ii].outX = arr[ii][0]*self->chInfo[ii].outWidth;
+ self->chInfo[ii].outY = chResolution.FrmStartY;
+
_G_OMX_INIT_PARAM (&algEnable);
algEnable.nPortIndex = ii;
algEnable.nChId = ii;
@@ -630,6 +839,7 @@ scaler_setup (GstOmxVideoMixer *omx_base)
if (err != OMX_ErrorNone)
return;
}
+
}
static void
@@ -642,6 +852,7 @@ omx_setup (GstOmxVideoMixer *omx_base)
self = GST_OMX_VIDEO_MIXER (omx_base);
gomx = (GOmxCore *) omx_base->gomx;
+
GST_INFO_OBJECT (omx_base, "begin");
/* enable input port */
@@ -660,6 +871,7 @@ omx_setup (GstOmxVideoMixer *omx_base)
/* indicate that port is now configured */
self->port_configured = TRUE;
+
GST_INFO_OBJECT (omx_base, "end");
}
@@ -744,13 +956,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;
@@ -798,6 +1013,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));
@@ -945,11 +1164,6 @@ wait_for_state (GOmxCore *core,
leave:
g_mutex_unlock (core->omx_state_mutex);
}
-//guint arr[3] = {1920,3840*1080/2,3840*1080/2+1920};
-//guint arr[3] = {1280,1280*720,1280*720+1280};
-guint arr[3][2] = { {1,0}, {0,1}, {1,1} };
-//guint arr[3] = {720,720*480,720*480+720};
-
void
vidmix_port_allocate_buffers (GstOmxVideoMixer *self)
@@ -969,7 +1183,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;
@@ -1015,9 +1229,11 @@ vidmix_port_allocate_buffers (GstOmxVideoMixer *self)
//printf("portidx op of buffer ip:%d, op:%d\n",port->buffers[i]->nInputPortIndex,port->buffers[i]->nOutputPortIndex);
+ //port->buffers[i]->nOffset = self->out_width;
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, &param);
size = param.nBufferSize;
@@ -1037,7 +1253,7 @@ vidmix_port_allocate_buffers (GstOmxVideoMixer *self)
port->port_index,
NULL,
size,
- (gchar*)buffer_data+(arr[ii -1][0]*self->out_width + arr[ii -1][1]*self->out_width*self->out_height));
+ (gchar*)buffer_data/*+(arr[ii -1][0]*self->out_width + arr[ii -1][1]*self->out_width*self->out_height)*/);
g_return_if_fail (port->buffers[i]);
@@ -1079,11 +1295,13 @@ videomixer_prepare (GstOmxVideoMixer *self,GOmxCore *core)
static void* vidmix_input_loop(void *arg) {
GstOmxVideoMixer *self = (GstOmxVideoMixer *)arg;
GOmxPort *port,*in_port;
- int ii;
+ int ii,kk;
GstBuffer * buf;
GOmxCore *gomx;
- int kk=0;
gint sent;
+ struct timeval tv;
+ guint64 afttime;
+ guint64 beftime;
port = self->in_port[0];
gomx = port->core;
@@ -1112,6 +1330,10 @@ static void* vidmix_input_loop(void *arg) {
gst_pad_start_task (self->srcpad, output_loop, self->srcpad);
}
+
+ if (gomx->omx_state != OMX_StateIdle) {
+ printf("Transition to idle failed!!\n");
+ }
}
//printf("inport enabled:%d\n",in_port->enabled);
@@ -1121,36 +1343,79 @@ static void* vidmix_input_loop(void *arg) {
if (G_UNLIKELY (gomx->omx_state == OMX_StateIdle))
{
GST_INFO_OBJECT (self, "omx: play");
+
g_omx_core_start (gomx);
+ if (gomx->omx_state != OMX_StateExecuting) {
+ printf("Transition to executing failed!!\n");
+ }
}
}
while(TRUE) {
- for(ii = 0; ii < NUM_PORTS; ii++) {
+ 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));*/
+ g_mutex_lock(self->loop_lock);
+ for(kk = 0; kk < NUM_PORTS; kk++) {
+ ii = self->orderList[kk]->idx;
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);
+ 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);
+ }else {
+ if(self->chInfo[ii].lastBuf) {
+ gst_buffer_unref(self->chInfo[ii].lastBuf);
+ }
+ self->chInfo[ii].lastBuf = buf;
}
- //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);
+ 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);
}
-
}
-
+ g_mutex_unlock(self->loop_lock);
}
leave:
//printf("leaving ip thread!!\n");
+ for(ii = 0; ii < NUM_PORTS; ii++)
+ if(self->chInfo[ii].lastBuf)
+ gst_buffer_unref(self->chInfo[ii].lastBuf);
+ g_mutex_unlock(self->loop_lock);
return NULL;
}
@@ -1193,7 +1458,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 */
@@ -1453,8 +1718,9 @@ sink_setcaps (GstPad *pad,
ch_info = (ip_params *)gst_pad_get_element_private(pad);
GST_INFO_OBJECT (self, "setcaps (sink): %" GST_PTR_FORMAT, caps);
- name = gst_caps_to_string(caps);
- g_free(name);
+ /* name = gst_caps_to_string(caps);
+ g_free(name); */
+
g_return_val_if_fail (caps, FALSE);
g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
@@ -1473,7 +1739,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");
@@ -1482,13 +1748,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);
@@ -1544,8 +1812,11 @@ type_instance_init (GTypeInstance *instance,
GstOmxVideoMixer *self;
GstElementClass *element_class;
GstOmxVideoMixerClass *bclass;
- int ii;
-
+ int ii,kk;
+ Olist tmp;
+ GstPadTemplate * templ;
+ GstVideoMixerPad *mixpad;
+
element_class = GST_ELEMENT_CLASS (g_class);
bclass = GST_OMX_VIDEO_MIXER_CLASS (g_class);
@@ -1572,21 +1843,37 @@ type_instance_init (GTypeInstance *instance,
self->numEosPending = NUM_PORTS;
self->eos = FALSE;
self->ready_lock = g_mutex_new ();
-
+ self->loop_lock = g_mutex_new ();
+
+ self->orderList = (guint*)g_malloc(sizeof(guint*)*NUM_PORTS);
+ templ = gst_element_class_get_pad_template (element_class, "sink");
for(ii = 0; ii < NUM_PORTS; ii++) {
gchar *name = g_strdup_printf ("sink_%02d", ii);
- self->sinkpad[ii] =
- gst_pad_new_from_template (gst_element_class_get_pad_template (element_class, "sink"), name);
-
+ /*self->sinkpad[ii] =
+ gst_pad_new_from_template (gst_element_class_get_pad_template (element_class, "sink"), name);*/
+ self->chInfo[ii].queue = async_queue_new ();
+ self->chInfo[ii].idx = ii;
+ self->chInfo[ii].eos = FALSE;
+ self->chInfo[ii].lastBuf = NULL;
+ self->chInfo[ii].order = 0;
+ self->chInfo[ii].outWidth = 0;
+ self->chInfo[ii].outHeight = 0;
+ self->chInfo[ii].outX = 0;
+ self->chInfo[ii].outY = 0;
+ mixpad = g_object_new (GST_TYPE_VIDEO_MIXER_PAD, "name", name, "direction",
+ templ->direction, "template", templ, NULL);
g_free(name);
+ self->sinkpad[ii] = (GstPad*)mixpad;
gst_pad_set_chain_function (self->sinkpad[ii], bclass->pad_chain);
gst_pad_set_event_function (self->sinkpad[ii], bclass->pad_event);
- self->chInfo[ii].queue = async_queue_new ();
- self->chInfo[ii].idx = ii;
- self->chInfo[ii].eos = FALSE;
+ self->orderList[ii] = (guint*)g_malloc(sizeof(Olist));
+ self->orderList[ii]->idx = ii;
+ self->orderList[ii]->order = self->chInfo[ii].order;
+ printf("queue_%d : %p\n",ii,self->chInfo[ii].queue);
+
gst_pad_set_element_private(self->sinkpad[ii], &(self->chInfo[ii]));
gst_element_add_pad (GST_ELEMENT (self), self->sinkpad[ii]);
@@ -1594,7 +1881,20 @@ type_instance_init (GTypeInstance *instance,
gst_pad_set_setcaps_function (self->sinkpad[ii],
GST_DEBUG_FUNCPTR (sink_setcaps));
}
-
+#if 1
+ for(ii=0;ii<NUM_PORTS;ii++)
+ for(kk=ii+1;kk<NUM_PORTS;kk++)
+ if(self->orderList[kk]->order < self->orderList[ii]->order) {
+ tmp = *(self->orderList[kk]);
+ *(self->orderList[kk]) = *(self->orderList[ii]);
+ *(self->orderList[ii]) = tmp;
+ }
+
+ printf("ip zorder - starting from lowest: %d",self->orderList[0]->idx);
+ for(ii=1;ii<NUM_PORTS;ii++)
+ printf(", %d",self->orderList[ii]->idx);
+ printf("\n");
+#endif
self->srcpad =
gst_pad_new_from_template (gst_element_class_get_pad_template (element_class, "src"), "src");
@@ -1607,7 +1907,13 @@ type_instance_init (GTypeInstance *instance,
gst_pad_set_setcaps_function (self->srcpad,
GST_DEBUG_FUNCPTR (src_setcaps));
- self->duration = GST_CLOCK_TIME_NONE;
+ 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");
}
View
18 omx/gstomx_videomixer.h
@@ -28,6 +28,7 @@
#include <OMX_TI_Common.h>
#include <omx_vfpc.h>
+#include "gstomx_videomixerpad.h"
G_BEGIN_DECLS
@@ -49,8 +50,19 @@ typedef struct ip_params {
gint in_width, in_height, in_stride;
AsyncQueue *queue;
gboolean eos;
+ GstBuffer *lastBuf;
+ guint order;
+ guint outWidth;
+ guint outHeight;
+ guint outX;
+ guint outY;
} ip_params ;
+typedef struct Olist {
+ guint idx;
+ gint order;
+} Olist ;
+
struct GstOmxVideoMixer
{
@@ -88,6 +100,12 @@ struct GstOmxVideoMixer
//gpointer g_class;
ip_params chInfo[NUM_PORTS];
guint numEosPending;
+ GSem *bufferSem;
+ GstClockTime timestamp;
+
+ guint settingsChanged;
+ Olist **orderList;
+ GMutex *loop_lock;
};
View
65 omx/gstomx_videomixerpad.h
@@ -0,0 +1,65 @@
+/* Video mixer pad
+ * Copyright (C) 2008 Wim Taymans <wim@fluendo.com>
+ *
+ * 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_VIDEO_MIXER_PAD_H__
+#define __GST_VIDEO_MIXER_PAD_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VIDEO_MIXER_PAD (gst_videomixer_pad_get_type())
+#define GST_VIDEO_MIXER_PAD(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_MIXER_PAD, GstVideoMixerPad))
+#define GST_VIDEO_MIXER_PAD_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_MIXER_PAD, GstVideoMixerPadiClass))
+#define GST_IS_VIDEO_MIXER_PAD(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_MIXER_PAD))
+#define GST_IS_VIDEO_MIXER_PAD_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_MIXER_PAD))
+
+typedef struct _GstVideoMixerPad GstVideoMixerPad;
+typedef struct _GstVideoMixerPadClass GstVideoMixerPadClass;
+
+/* all information needed for one video stream */
+struct _GstVideoMixerPad
+{
+ GstPad parent; /* subclass the pad */
+
+ gint64 queued;
+
+ guint in_width, in_height;
+ gint fps_n;
+ gint fps_d;
+ gint par_n;
+ gint par_d;
+
+ gint xpos, ypos;
+ guint zorder;
+ gint blend_mode;
+ gdouble alpha;
+};
+
+struct _GstVideoMixerPadClass
+{
+ GstPadClass parent_class;
+};
+
+G_END_DECLS
+#endif /* __GST_VIDEO_MIXER_PAD_H__ */
View
348 omx/gstomxbufferalloc.c
@@ -0,0 +1,348 @@
+/*
+ * GStreamer
+ * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
+ * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2011 prashant <<user@hostname.org>>
+ *
+ * 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.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v -m fakesrc ! omxbufferalloc ! fakesink silent=TRUE
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gst/gst.h>
+#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 <<user@hostname.org>>");
+
+ 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();