static GstFlowReturn
push_buffer (GstOmxBaseFilter2 *self,
             GstBuffer *buf)
{
    GstFlowReturn ret = GST_FLOW_ERROR;
	int i;

	for (i = 0; i< NUM_OUTPUTS; i++) {
		if (GST_GET_OMXPORT(buf) == self->out_port[i]) {
			break;
		}
	}

	if (i == NUM_OUTPUTS) return ret;

    GST_BUFFER_DURATION (buf) = self->duration;

	if (self->gomx->gen_timestamps == TRUE) {
		if (GST_CLOCK_TIME_NONE == GST_BUFFER_TIMESTAMP(buf) && 
		    GST_CLOCK_TIME_NONE != self->last_buf_timestamp[i] &&
		    GST_CLOCK_TIME_NONE != self->duration) {
			GST_BUFFER_TIMESTAMP(buf) = self->last_buf_timestamp[i] + self->duration;
		}
		self->last_buf_timestamp[i] = GST_BUFFER_TIMESTAMP(buf);
	}

    PRINT_BUFFER (self, buf);
    if (self->push_cb) {
        if (FALSE == self->push_cb (self, buf)) { gst_buffer_unref(buf); return GST_FLOW_OK; }
	}

	/** @todo check if tainted */
	GST_LOG_OBJECT (self, "begin");
	ret = gst_pad_push (self->srcpad[i], buf);
	GST_LOG_OBJECT (self, "end");

    return ret;
}
static GstFlowReturn
push_buffer (GstOmxBaseFilter21 *self,
             GstBuffer *buf)
{
    GstFlowReturn ret = GST_FLOW_ERROR;
	int i;

	if(GST_GET_OMXPORT(buf) != self->out_port){
		return ret;
	}
    GST_BUFFER_DURATION (buf) = self->duration;
	GST_BUFFER_TIMESTAMP(buf) = self->sink_camera_timestamp;
	GST_DEBUG_OBJECT(self, "timestamp=%" GST_TIME_FORMAT, GST_TIME_ARGS(self->sink_camera_timestamp));

    PRINT_BUFFER (self, buf);
    if (self->push_cb) {
        if (FALSE == self->push_cb (self, buf)) { gst_buffer_unref(buf); return GST_FLOW_OK; }
	}

	/** @todo check if tainted */
	ret = gst_pad_push (self->srcpad, buf);

    return ret;
}
static GstFlowReturn
pad_chain (GstPad *pad,
           GstBuffer *buf)
{
    GOmxCore *gomx;
    GOmxPort *in_port;
    GstOmxBaseFilter2 *self;
    GstFlowReturn ret = GST_FLOW_OK;
	int i;

    self = GST_OMX_BASE_FILTER2 (GST_OBJECT_PARENT (pad));

    //printf("INput!!\n");
    PRINT_BUFFER (self, buf);

    gomx = self->gomx;

    GST_LOG_OBJECT (self, "begin: size=%u, state=%d", GST_BUFFER_SIZE (buf), gomx->omx_state);

    if (G_UNLIKELY (gomx->omx_state == OMX_StateLoaded))
    {
        g_mutex_lock (self->ready_lock);

        GST_INFO_OBJECT (self, "omx: prepare");
        
        /** @todo this should probably go after doing preparations. */
        if (self->omx_setup)
        {
            self->omx_setup (self);
        }

        setup_input_buffer (self, buf);

        setup_ports (self);

        g_omx_core_prepare (self->gomx);

        if (gomx->omx_state == OMX_StateIdle)
        {
            self->ready = TRUE;
			for (i = 0; i < NUM_OUTPUTS; i++) 
            	gst_pad_start_task (self->srcpad[i], output_loop, self->srcpad[i]);
        }

        g_mutex_unlock (self->ready_lock);

        if (gomx->omx_state != OMX_StateIdle)
            goto out_flushing;
    }

    in_port = self->in_port;

    if (G_LIKELY (in_port->enabled))
    {        
        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)
                goto out_flushing;

            /* send buffer with codec data flag */
            if (self->codec_data)
            {
                GST_BUFFER_FLAG_SET (self->codec_data, GST_BUFFER_FLAG_IN_CAPS);  /* just in case */
                g_omx_port_send (in_port, self->codec_data);
            }

        }

        if (G_UNLIKELY (gomx->omx_state != OMX_StateExecuting))
        {
            GST_ERROR_OBJECT (self, "Whoa! very wrong");
        }

        while (TRUE)
        {
            gint sent;

            if (self->last_pad_push_return != GST_FLOW_OK ||
                !(gomx->omx_state == OMX_StateExecuting ||
                  gomx->omx_state == OMX_StatePause))
            {
                GST_DEBUG_OBJECT (self, "last_pad_push_return=%d", self->last_pad_push_return);
                goto out_flushing;
            }

			if (self->input_fields_separately) {
				g_omx_port_send_interlaced_fields (in_port, buf, self->second_field_offset);
                gst_buffer_unref (buf);
				break;
			}

            sent = g_omx_port_send (in_port, buf);

            if (G_UNLIKELY (sent < 0))
            {
                ret = GST_FLOW_WRONG_STATE;
                goto out_flushing;
            }
            else if (sent < GST_BUFFER_SIZE (buf))
            {
                GstBuffer *subbuf = gst_buffer_create_sub (buf, sent,
                        GST_BUFFER_SIZE (buf) - sent);
                gst_buffer_unref (buf);
                buf = subbuf;
            }
            else
            {
                gst_buffer_unref (buf);
                break;
            }
        }
    }
    else
    {
        GST_WARNING_OBJECT (self, "done");
        ret = GST_FLOW_UNEXPECTED;
    }

leave:

    GST_LOG_OBJECT (self, "end");

    return ret;

    /* special conditions */
out_flushing:
    {
        const gchar *error_msg = NULL;

        if (gomx->omx_error)
        {
            error_msg = "Error from OpenMAX component";
        }
        else if (gomx->omx_state != OMX_StateExecuting &&
                 gomx->omx_state != OMX_StatePause)
        {
            error_msg = "OpenMAX component in wrong state";
        }

        if (error_msg)
        {
            GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), (error_msg));
            ret = GST_FLOW_ERROR;
        }

        gst_buffer_unref (buf);

        goto leave;
    }
}
static GstFlowReturn
pad_chain (GstPad *pad,
           GstBuffer *buf)
{
    GOmxCore *gomx;
    GOmxPort *in_port;
    GstOmxBaseFilter21 *self;
    GstFlowReturn ret = GST_FLOW_OK;
	int i;
	static sink_init = 0;
	int sink_number;
	static gboolean init_done = FALSE;
	
    self = GST_OMX_BASE_FILTER21 (GST_OBJECT_PARENT (pad));
	if(strcmp(GST_PAD_NAME(pad), "sink_00") == 0){
		sink_number=0;
        self->sink_camera_timestamp = GST_BUFFER_TIMESTAMP(buf);
	}
	else if(strcmp(GST_PAD_NAME(pad), "sink_01") == 0){
		sink_number=1;
	}
    PRINT_BUFFER (self, buf);

    gomx = self->gomx;

    GST_LOG_OBJECT (self, "begin: size=%u, state=%d, sink_number=%d", GST_BUFFER_SIZE (buf), gomx->omx_state, sink_number);
	
	/*if (G_LIKELY (gomx->omx_state != OMX_StateExecuting))
    {
		GST_INFO_OBJECT (self, "Begin - Port %d", sink_number);
		//setup_input_buffer (self, buf, sink_number);
		//sink_init++;
		//g_mutex_lock (self->ready_lock);
		if(init_done == TRUE){
			GST_INFO_OBJECT (self, "Init_done");
			//g_mutex_unlock(self->ready_lock);
		}
		if(init_done == TRUE){
			sink_init = 0;
			init_done = FALSE;

		}
		else{
			while(sink_init != 2){
				usleep(1000);
			}
		}
	}*/
	
    if (G_UNLIKELY (gomx->omx_state == OMX_StateLoaded))
    {

        GST_INFO_OBJECT (self, "omx: prepare");
        
        /** @todo this should probably go after doing preparations. */
        if (self->omx_setup)
        {
            self->omx_setup (self);
        }
        
        /* enable input port */
        for(i=0;i<NUM_INPUTS;i++){
			GST_INFO_OBJECT (self,"Enable Port %d",self->in_port[i]->port_index);
			OMX_SendCommand (gomx->omx_handle, OMX_CommandPortEnable, self->in_port[i]->port_index, NULL);
			g_sem_down (self->in_port[i]->core->port_sem);
		}
		GST_INFO_OBJECT (self,"Enable Port %d",self->out_port->port_index);
		/* enable output port */
		OMX_SendCommand (gomx->omx_handle,OMX_CommandPortEnable, self->out_port->port_index, NULL);
		g_sem_down (self->out_port->core->port_sem);

		/* indicate that port is now configured */

        setup_ports (self);

        g_omx_core_prepare (self->gomx);

        if (gomx->omx_state == OMX_StateIdle)
        {
            self->ready = TRUE;
           	//gst_pad_start_task (self->srcpad, output_loop, self->srcpad);
        }
        
        if (gomx->omx_state != OMX_StateIdle)
            goto out_flushing;
        
        GST_INFO_OBJECT (self, "omx: end state Loaded");    
    }
    
    if (G_UNLIKELY (gomx->omx_state == OMX_StateIdle))
	{
		g_omx_core_start (gomx);
		GST_INFO_OBJECT (self, "Release Port - %d", sink_number);
		init_done = TRUE;
		//g_mutex_unlock (self->ready_lock);
		if (gomx->omx_state != OMX_StateExecuting){
			GST_INFO_OBJECT (self, "omx: executing FAILED !");
			goto out_flushing;
		
		}
	}
	
	if (G_LIKELY (self->in_port[sink_number]->enabled))
	{	      
		

		if (G_UNLIKELY (gomx->omx_state != OMX_StateExecuting))
		{
			GST_ERROR_OBJECT (self, "Whoa! very wrong");
		}

		while (TRUE)
		{
			gint sent;
			if (self->last_pad_push_return != GST_FLOW_OK ||
				!(gomx->omx_state == OMX_StateExecuting ||
				gomx->omx_state == OMX_StatePause))
			{
				GST_INFO_OBJECT (self, "last_pad_push_return=%d", self->last_pad_push_return);
				goto out_flushing;
			}
			sent = g_omx_port_send (self->in_port[sink_number], buf);
			if (G_UNLIKELY (sent < 0))
			{
				ret = GST_FLOW_WRONG_STATE;
				goto out_flushing;
			}
			else if (sent < GST_BUFFER_SIZE (buf))
			{
				GstBuffer *subbuf = gst_buffer_create_sub (buf, sent,
						GST_BUFFER_SIZE (buf) - sent);
				gst_buffer_unref (buf);
				buf = subbuf;
			}
			else
			{
				gst_buffer_unref (buf);

				break;
			}
			
		}
	}
	else
	{
		GST_WARNING_OBJECT (self, "done");
		ret = GST_FLOW_UNEXPECTED;
	}
	return ret;
leave:

    GST_LOG_OBJECT (self, "end");

    return ret;

    /* special conditions */
out_flushing:
    {
        const gchar *error_msg = NULL;

        if (gomx->omx_error)
        {
            error_msg = "Error from OpenMAX component";
        }
        else if (gomx->omx_state != OMX_StateExecuting &&
                 gomx->omx_state != OMX_StatePause)
        {
            error_msg = "OpenMAX component in wrong state";
        }

        if (error_msg)
        {
            GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), (error_msg));
            ret = GST_FLOW_ERROR;
        }

        gst_buffer_unref (buf);

        goto leave;
    }
}
/* protected helper method which can be used by derived classes:
 */
GstFlowReturn
gst_omx_base_src_create_from_port (GstOmxBaseSrc *self,
                                   GOmxPort *out_port,
                                   GstBuffer **ret_buf)
{
    GOmxCore *gomx;
    GstFlowReturn ret = GST_FLOW_OK;

    gomx = self->gomx;

    GST_LOG_OBJECT (self, "begin");

    if (out_port->enabled)
    {
        if (G_UNLIKELY (gomx->omx_state == OMX_StateIdle))
        {
            GST_INFO_OBJECT (self, "omx: play");
            g_omx_core_start (gomx);
        }

        if (G_UNLIKELY (gomx->omx_state != OMX_StateExecuting))
        {
            GST_ERROR_OBJECT (self, "Whoa! very wrong");
            ret = GST_FLOW_ERROR;
            goto beach;
        }

        while (out_port->enabled)
        {
            gpointer obj = g_omx_port_recv (out_port);

            if (G_UNLIKELY (!obj))
            {
                ret = GST_FLOW_ERROR;
                break;
            }

            if (G_LIKELY (GST_IS_BUFFER (obj)))
            {
                GstBuffer *buf = GST_BUFFER (obj);
                if (G_LIKELY (GST_BUFFER_SIZE (buf) > 0))
                {
                    PRINT_BUFFER (self, buf);
                    *ret_buf = buf;
                    break;
                }
            }
            else if (GST_IS_EVENT (obj))
            {
                GST_INFO_OBJECT (self, "got eos");
                g_omx_core_set_done (gomx);
                break;
            }
        }
    }

    if (!out_port->enabled)
    {
        GST_WARNING_OBJECT (self, "done");
        ret = GST_FLOW_UNEXPECTED;
    }

beach:

    GST_LOG_OBJECT (self, "end");

    return ret;
}