static GstFlowReturn
create (GstBaseSrc *gst_base,
        guint64 offset,
        guint length,
        GstBuffer **ret_buf)
{
    GstOmxBaseSrc *self = GST_OMX_BASE_SRC (gst_base);

    GST_LOG_OBJECT (self, "state: %d", self->gomx->omx_state);

    if (self->gomx->omx_state == OMX_StateLoaded)
    {
        GST_INFO_OBJECT (self, "omx: prepare");

        gst_omx_base_src_setup_ports (self);
        g_omx_core_prepare (self->gomx);
    }

    return gst_omx_base_src_create_from_port (self, self->out_port, ret_buf);
}
static GstStateChangeReturn
change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
  GstOmxBaseSink *self;

  self = GST_OMX_BASE_SINK (element);

  GST_LOG_OBJECT (self, "begin");

  GST_INFO_OBJECT (self, "changing state %s - %s",
      gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
      gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      if (!self->initialized) {
        if (!omx_init (self))
          return GST_PAD_LINK_REFUSED;

        self->initialized = TRUE;
      }

      g_omx_core_prepare (self->gomx);
      break;

    case GST_STATE_CHANGE_READY_TO_PAUSED:
      g_omx_core_start (self->gomx);
      break;

    case GST_STATE_CHANGE_PAUSED_TO_READY:
      g_omx_port_finish (self->in_port);
      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_PLAYING_TO_PAUSED:
      g_omx_port_pause (self->in_port);
      break;

    case GST_STATE_CHANGE_PAUSED_TO_READY:
      g_omx_core_stop (self->gomx);
      break;

    case GST_STATE_CHANGE_READY_TO_NULL:
      g_omx_core_unload (self->gomx);
      break;

    default:
      break;
  }

leave:
  GST_LOG_OBJECT (self, "end");

  return ret;
}
static GstFlowReturn
render (GstBaseSink *gst_base,
        GstBuffer *buf)
{
    GOmxCore *gomx;
    GOmxPort *in_port;
    GstOmxBaseSink *self;
    GstFlowReturn ret = GST_FLOW_OK;

    self = GST_OMX_BASE_SINK (gst_base);

    gomx = self->gomx;

    GST_LOG_OBJECT (self, "begin");
    GST_LOG_OBJECT (self, "gst_buffer: size=%lu", GST_BUFFER_SIZE (buf));

    GST_LOG_OBJECT (self, "state: %d", gomx->omx_state);

    if (G_UNLIKELY (gomx->omx_state == OMX_StateLoaded))
    {
        GST_INFO_OBJECT (self, "omx: prepare");

        setup_ports (self);
        g_omx_core_prepare (self->gomx);
    }

    in_port = self->in_port;

    if (G_LIKELY (in_port->enabled))
    {
        guint buffer_offset = 0;

        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");
        }

        while (G_LIKELY (buffer_offset < GST_BUFFER_SIZE (buf)))
        {
            OMX_BUFFERHEADERTYPE *omx_buffer;

            GST_LOG_OBJECT (self, "request_buffer");
            omx_buffer = g_omx_port_request_buffer (in_port);

            if (G_LIKELY (omx_buffer))
            {
                GST_DEBUG_OBJECT (self, "omx_buffer: size=%lu, len=%lu, flags=%lu, offset=%lu, timestamp=%lld",
                                  omx_buffer->nAllocLen, omx_buffer->nFilledLen, omx_buffer->nFlags,
                                  omx_buffer->nOffset, omx_buffer->nTimeStamp);

                if (omx_buffer->nOffset == 0 &&
                        share_input_buffer)
                {
                    {
                        GstBuffer *old_buf;
                        old_buf = omx_buffer->pAppPrivate;

                        if (old_buf)
                        {
                            gst_buffer_unref (old_buf);
                        }
                        else if (omx_buffer->pBuffer)
                        {
                            g_free (omx_buffer->pBuffer);
                        }
                    }

                    /* We are going to use this. */
                    gst_buffer_ref (buf);

                    omx_buffer->pBuffer = GST_BUFFER_DATA (buf);
                    omx_buffer->nAllocLen = GST_BUFFER_SIZE (buf);
                    omx_buffer->nFilledLen = GST_BUFFER_SIZE (buf);
                    omx_buffer->pAppPrivate = buf;
                }
                else
                {
                    omx_buffer->nFilledLen = MIN (GST_BUFFER_SIZE (buf) - buffer_offset,
                                                  omx_buffer->nAllocLen - omx_buffer->nOffset);
                    memcpy (omx_buffer->pBuffer + omx_buffer->nOffset, GST_BUFFER_DATA (buf) + buffer_offset, omx_buffer->nFilledLen);
                }

                GST_LOG_OBJECT (self, "release_buffer");
                g_omx_port_release_buffer (in_port, omx_buffer);

                buffer_offset += omx_buffer->nFilledLen;
            }
            else
            {
                GST_WARNING_OBJECT (self, "null buffer");
                /* ret = GST_FLOW_ERROR; */
            }
        }
    }
    else
    {
        GST_WARNING_OBJECT (self, "done");
        ret = GST_FLOW_UNEXPECTED;
    }

    GST_LOG_OBJECT (self, "end");

    return ret;
}
static GstFlowReturn
create (GstBaseSrc * gst_base,
    guint64 offset, guint length, GstBuffer ** ret_buf)
{
  GOmxCore *gomx;
  GOmxPort *out_port;
  GstOmxBaseSrc *self;
  GstFlowReturn ret = GST_FLOW_OK;

  self = GST_OMX_BASE_SRC (gst_base);

  gomx = self->gomx;

  GST_LOG_OBJECT (self, "begin");

  GST_LOG_OBJECT (self, "state: %d", gomx->omx_state);

  if (gomx->omx_state == OMX_StateLoaded) {
    GST_INFO_OBJECT (self, "omx: prepare");

    setup_ports (self);
    g_omx_core_prepare (self->gomx);
  }

  out_port = self->out_port;

  while (out_port->enabled) {
    switch (gomx->omx_state) {
      case OMX_StateIdle:
      {
        GST_INFO_OBJECT (self, "omx: play");
        g_omx_core_start (gomx);
      }
        break;
      default:
        break;
    }

    switch (gomx->omx_state) {
      case OMX_StateExecuting:
        /* OK */
        break;
      default:
        GST_ERROR_OBJECT (self, "Whoa! very wrong");
        break;
    }

    {
      OMX_BUFFERHEADERTYPE *omx_buffer;

      GST_LOG_OBJECT (self, "request_buffer");
      omx_buffer = g_omx_port_request_buffer (out_port);

      if (omx_buffer) {
        GST_DEBUG_OBJECT (self, "omx_buffer: size=%lu, len=%lu, offset=%lu",
            omx_buffer->nAllocLen, omx_buffer->nFilledLen, omx_buffer->nOffset);

        if (omx_buffer->nFlags & OMX_BUFFERFLAG_EOS) {
          GST_INFO_OBJECT (self, "got eos");
          g_omx_core_set_done (gomx);
          break;
        }

        if (omx_buffer->nFilledLen > 0) {
          GstBuffer *buf;

          if (out_port->enabled) {
            GstCaps *caps = NULL;

            caps = gst_pad_get_negotiated_caps (gst_base->srcpad);

            if (!caps) {
                            /** @todo We shouldn't be doing this. */
              GST_WARNING_OBJECT (self, "somebody didn't do his work");
              gomx->settings_changed_cb (gomx);
            } else {
              GST_LOG_OBJECT (self, "caps already fixed");
              gst_caps_unref (caps);
            }
          }

          buf = omx_buffer->pAppPrivate;

          if (buf && !(omx_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
            GST_BUFFER_SIZE (buf) = omx_buffer->nFilledLen;
#if 0
            if (self->use_timestamps) {
              GST_BUFFER_TIMESTAMP (buf) =
                  omx_buffer->nTimeStamp * (GST_SECOND / OMX_TICKS_PER_SECOND);
            }
#endif

            omx_buffer->pAppPrivate = NULL;
            omx_buffer->pBuffer = NULL;
            omx_buffer->nFilledLen = 0;

            *ret_buf = buf;

            gst_buffer_unref (buf);
          } else {
            /* This is only meant for the first OpenMAX buffers,
             * which need to be pre-allocated. */
            /* Also for the very last one. */
            gst_pad_alloc_buffer_and_set_caps (gst_base->srcpad,
                GST_BUFFER_OFFSET_NONE,
                omx_buffer->nFilledLen, GST_PAD_CAPS (gst_base->srcpad), &buf);

            if (buf) {
              GST_WARNING_OBJECT (self, "couldn't zero-copy");
              memcpy (GST_BUFFER_DATA (buf),
                  omx_buffer->pBuffer + omx_buffer->nOffset,
                  omx_buffer->nFilledLen);
#if 0
              if (self->use_timestamps) {
                GST_BUFFER_TIMESTAMP (buf) =
                    omx_buffer->nTimeStamp * (GST_SECOND /
                    OMX_TICKS_PER_SECOND);
              }
#endif

              omx_buffer->nFilledLen = 0;
              g_free (omx_buffer->pBuffer);
              omx_buffer->pBuffer = NULL;

              *ret_buf = buf;
            } else {
              GST_ERROR_OBJECT (self, "whoa!");
            }
          }

          if (!omx_buffer->pBuffer) {
            GstBuffer *new_buf;
            GstFlowReturn result;

            GST_LOG_OBJECT (self, "allocate buffer");
            result = gst_pad_alloc_buffer_and_set_caps (gst_base->srcpad,
                GST_BUFFER_OFFSET_NONE,
                omx_buffer->nAllocLen,
                GST_PAD_CAPS (gst_base->srcpad), &new_buf);

            if (result == GST_FLOW_OK) {
              gst_buffer_ref (new_buf);
              omx_buffer->pAppPrivate = new_buf;

              omx_buffer->pBuffer = GST_BUFFER_DATA (new_buf);
              omx_buffer->nAllocLen = GST_BUFFER_SIZE (new_buf);
            } else {
              GST_WARNING_OBJECT (self, "could not allocate buffer");
              omx_buffer->pBuffer = g_malloc (omx_buffer->nAllocLen);
            }
          }

          GST_LOG_OBJECT (self, "release_buffer");
          g_omx_port_release_buffer (out_port, omx_buffer);
          break;
        } else {
          GST_WARNING_OBJECT (self, "empty buffer");
          GST_LOG_OBJECT (self, "release_buffer");
          g_omx_port_release_buffer (out_port, omx_buffer);
          continue;
        }
      } else {
        GST_WARNING_OBJECT (self, "null buffer");
        /* ret = GST_FLOW_ERROR; */
        break;
      }
    }
  }

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

  GST_LOG_OBJECT (self, "end");

  return ret;
}
Example #5
0
static GstFlowReturn
pad_chain (GstPad *pad,
           GstBuffer *buf)
{
    GOmxCore *gomx;
    GOmxPort *in_port;
    GstOmxBaseFilter *self;
    GstFlowReturn ret = GST_FLOW_OK;

    self = GST_OMX_BASE_FILTER (GST_OBJECT_PARENT (pad));

    gomx = self->gomx;

    GST_LOG_OBJECT (self, "begin");
    GST_LOG_OBJECT (self, "gst_buffer: size=%u", GST_BUFFER_SIZE (buf));

    GST_LOG_OBJECT (self, "state: %d", 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_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);
        }

        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))
    {
        guint buffer_offset = 0;

        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 */
            /** @todo move to util */
            if (self->codec_data)
            {
                OMX_BUFFERHEADERTYPE *omx_buffer;

                GST_LOG_OBJECT (self, "request buffer");
                omx_buffer = g_omx_port_request_buffer (in_port);

                if (G_LIKELY (omx_buffer))
                {
                    omx_buffer->nFlags |= 0x00000080; /* codec data flag */

                    omx_buffer->nFilledLen = GST_BUFFER_SIZE (self->codec_data);
                    memcpy (omx_buffer->pBuffer + omx_buffer->nOffset, GST_BUFFER_DATA (self->codec_data), omx_buffer->nFilledLen);

                    GST_LOG_OBJECT (self, "release_buffer");
                    g_omx_port_release_buffer (in_port, omx_buffer);
                }
            }
        }

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

        while (G_LIKELY (buffer_offset < GST_BUFFER_SIZE (buf)))
        {
            OMX_BUFFERHEADERTYPE *omx_buffer;

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

            GST_LOG_OBJECT (self, "request buffer");
            omx_buffer = g_omx_port_request_buffer (in_port);

            GST_LOG_OBJECT (self, "omx_buffer: %p", omx_buffer);

            if (G_LIKELY (omx_buffer))
            {
                GST_DEBUG_OBJECT (self, "omx_buffer: size=%lu, len=%lu, flags=%lu, offset=%lu, timestamp=%lld",
                                  omx_buffer->nAllocLen, omx_buffer->nFilledLen, omx_buffer->nFlags,
                                  omx_buffer->nOffset, omx_buffer->nTimeStamp);

                if (omx_buffer->nOffset == 0 &&
                    self->share_input_buffer)
                {
                    {
                        GstBuffer *old_buf;
                        old_buf = omx_buffer->pAppPrivate;

                        if (old_buf)
                        {
                            gst_buffer_unref (old_buf);
                        }
                        else if (omx_buffer->pBuffer)
                        {
                            g_free (omx_buffer->pBuffer);
                        }
                    }

                    omx_buffer->pBuffer = GST_BUFFER_DATA (buf);
                    omx_buffer->nAllocLen = GST_BUFFER_SIZE (buf);
                    omx_buffer->nFilledLen = GST_BUFFER_SIZE (buf);
                    omx_buffer->pAppPrivate = buf;
                }
                else
                {
                    omx_buffer->nFilledLen = MIN (GST_BUFFER_SIZE (buf) - buffer_offset,
                                                  omx_buffer->nAllocLen - omx_buffer->nOffset);
                    memcpy (omx_buffer->pBuffer + omx_buffer->nOffset, GST_BUFFER_DATA (buf) + buffer_offset, omx_buffer->nFilledLen);
                }

                if (self->use_timestamps)
                {
                    GstClockTime timestamp_offset = 0;

                    if (buffer_offset && GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE)
                    {
                        timestamp_offset = gst_util_uint64_scale_int (buffer_offset,
                                                                      GST_BUFFER_DURATION (buf),
                                                                      GST_BUFFER_SIZE (buf));
                    }

                    omx_buffer->nTimeStamp = gst_util_uint64_scale_int (GST_BUFFER_TIMESTAMP (buf) + timestamp_offset,
                                                                        OMX_TICKS_PER_SECOND,
                                                                        GST_SECOND);
                }

                buffer_offset += omx_buffer->nFilledLen;

                GST_LOG_OBJECT (self, "release_buffer");
                /** @todo untaint buffer */
                g_omx_port_release_buffer (in_port, omx_buffer);
            }
            else
            {
                GST_WARNING_OBJECT (self, "null buffer");
                ret = GST_FLOW_WRONG_STATE;
                goto out_flushing;
            }
        }
    }
    else
    {
        GST_WARNING_OBJECT (self, "done");
        ret = GST_FLOW_UNEXPECTED;
    }

    if (!self->share_input_buffer)
    {
        gst_buffer_unref (buf);
    }

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;
    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;
    }
}
static void
output_loop (gpointer data)
{
  GstPad *pad;
  GOmxCore *gomx;
  GOmxPort *out_port;
  GstOmxBaseFilter *self;
  GstFlowReturn ret = GST_FLOW_OK;

  pad = data;
  self = GST_OMX_BASE_FILTER (gst_pad_get_parent (pad));
  gomx = self->gomx;

  GST_LOG_OBJECT (self, "begin");

  /* do not bother if we have been setup to bail out */
  if ((ret = g_atomic_int_get (&self->last_pad_push_return)) != GST_FLOW_OK)
    goto leave;

  if (!self->ready) {
    g_error ("not ready");
    return;
  }

  out_port = self->out_port;

  if (G_LIKELY (out_port->enabled)) {
    OMX_BUFFERHEADERTYPE *omx_buffer = NULL;

    GST_LOG_OBJECT (self, "request buffer");
    omx_buffer = g_omx_port_request_buffer (out_port);

    GST_LOG_OBJECT (self, "omx_buffer: %p", omx_buffer);

    if (G_UNLIKELY (!omx_buffer)) {
      GST_WARNING_OBJECT (self, "null buffer: leaving");
      ret = GST_FLOW_WRONG_STATE;
      goto leave;
    }

    log_buffer (self, omx_buffer);

    if (G_LIKELY (omx_buffer->nFilledLen > 0)) {
      GstBuffer *buf;

#if 1
            /** @todo remove this check */
      if (G_LIKELY (self->in_port->enabled)) {
        GstCaps *caps = NULL;

        caps = gst_pad_get_negotiated_caps (self->srcpad);

#ifdef ANDROID
        if (!caps || gomx->settings_changed) {
#else
        if (!caps) {
#endif
                    /** @todo We shouldn't be doing this. */
          GST_WARNING_OBJECT (self, "faking settings changed notification");
          if (gomx->settings_changed_cb)
            gomx->settings_changed_cb (gomx);
#ifdef ANDROID
          gomx->settings_changed = FALSE;
#endif
        } else {
          GST_LOG_OBJECT (self, "caps already fixed: %" GST_PTR_FORMAT, caps);
          gst_caps_unref (caps);
        }
      }
#endif

      /* buf is always null when the output buffer pointer isn't shared. */
      buf = omx_buffer->pAppPrivate;

            /** @todo we need to move all the caps handling to one single
             * place, in the output loop probably. */
      if (G_UNLIKELY (omx_buffer->nFlags & 0x80)) {
        GstCaps *caps = NULL;
        GstStructure *structure;
        GValue value = { 0, {{0}
            }
        };

        caps = gst_pad_get_negotiated_caps (self->srcpad);
        caps = gst_caps_make_writable (caps);
        structure = gst_caps_get_structure (caps, 0);

        g_value_init (&value, GST_TYPE_BUFFER);
        buf = gst_buffer_new_and_alloc (omx_buffer->nFilledLen);
        memcpy (GST_BUFFER_DATA (buf),
            omx_buffer->pBuffer + omx_buffer->nOffset, omx_buffer->nFilledLen);
        gst_value_set_buffer (&value, buf);
        gst_buffer_unref (buf);
        gst_structure_set_value (structure, "codec_data", &value);
        g_value_unset (&value);

        gst_pad_set_caps (self->srcpad, caps);
      } else if (buf && !(omx_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
        GST_BUFFER_SIZE (buf) = omx_buffer->nFilledLen;
        if (self->use_timestamps) {
          GST_BUFFER_TIMESTAMP (buf) =
              gst_util_uint64_scale_int (omx_buffer->nTimeStamp, GST_SECOND,
              OMX_TICKS_PER_SECOND);
        }

        omx_buffer->pAppPrivate = NULL;
        omx_buffer->pBuffer = NULL;

        ret = push_buffer (self, buf);

        gst_buffer_unref (buf);
      } else {
        /* This is only meant for the first OpenMAX buffers,
         * which need to be pre-allocated. */
        /* Also for the very last one. */
        ret = gst_pad_alloc_buffer_and_set_caps (self->srcpad,
            GST_BUFFER_OFFSET_NONE,
            omx_buffer->nFilledLen, GST_PAD_CAPS (self->srcpad), &buf);

        if (G_LIKELY (buf)) {
          memcpy (GST_BUFFER_DATA (buf),
              omx_buffer->pBuffer + omx_buffer->nOffset,
              omx_buffer->nFilledLen);
          if (self->use_timestamps) {
            GST_BUFFER_TIMESTAMP (buf) =
                gst_util_uint64_scale_int (omx_buffer->nTimeStamp, GST_SECOND,
                OMX_TICKS_PER_SECOND);
          }

          if (self->share_output_buffer) {
            GST_WARNING_OBJECT (self, "couldn't zero-copy");
            /* If pAppPrivate is NULL, it means it was a dummy
             * allocation, free it. */
            if (!omx_buffer->pAppPrivate) {
              g_free (omx_buffer->pBuffer);
              omx_buffer->pBuffer = NULL;
            }
          }

          ret = push_buffer (self, buf);
        } else {
          GST_WARNING_OBJECT (self, "couldn't allocate buffer of size %lu",
              omx_buffer->nFilledLen);
        }
      }
    } else {
      GST_WARNING_OBJECT (self, "empty buffer");
    }

    if (self->share_output_buffer &&
        !omx_buffer->pBuffer && omx_buffer->nOffset == 0) {
      GstBuffer *buf;
      GstFlowReturn result;

      GST_LOG_OBJECT (self, "allocate buffer");
      result = gst_pad_alloc_buffer_and_set_caps (self->srcpad,
          GST_BUFFER_OFFSET_NONE,
          omx_buffer->nAllocLen, GST_PAD_CAPS (self->srcpad), &buf);

      if (G_LIKELY (result == GST_FLOW_OK)) {
        gst_buffer_ref (buf);
        omx_buffer->pAppPrivate = buf;

        omx_buffer->pBuffer = GST_BUFFER_DATA (buf);
        omx_buffer->nAllocLen = GST_BUFFER_SIZE (buf);
      } else {
        GST_WARNING_OBJECT (self,
            "could not pad allocate buffer, using malloc");
        omx_buffer->pBuffer = g_malloc (omx_buffer->nAllocLen);
      }
    }

    if (self->share_output_buffer && !omx_buffer->pBuffer) {
      GST_ERROR_OBJECT (self, "no input buffer to share");
    }

    if (G_UNLIKELY (omx_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
      GST_DEBUG_OBJECT (self, "got eos");
      gst_pad_push_event (self->srcpad, gst_event_new_eos ());
      omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
      ret = GST_FLOW_UNEXPECTED;
    }

    omx_buffer->nFilledLen = 0;
    GST_LOG_OBJECT (self, "release_buffer");
    g_omx_port_release_buffer (out_port, omx_buffer);
  }

leave:

  self->last_pad_push_return = ret;

  if (gomx->omx_error != OMX_ErrorNone)
    ret = GST_FLOW_ERROR;

  if (ret != GST_FLOW_OK) {
    GST_INFO_OBJECT (self, "pause task, reason:  %s", gst_flow_get_name (ret));
    gst_pad_pause_task (self->srcpad);
  }

  GST_LOG_OBJECT (self, "end");

  gst_object_unref (self);
}

static GstFlowReturn
pad_chain (GstPad * pad, GstBuffer * buf)
{
  GOmxCore *gomx;
  GOmxPort *in_port;
  GstOmxBaseFilter *self;
  GstFlowReturn ret = GST_FLOW_OK;

  self = GST_OMX_BASE_FILTER (GST_OBJECT_PARENT (pad));

  gomx = self->gomx;

  GST_LOG_OBJECT (self, "begin");
  GST_LOG_OBJECT (self, "gst_buffer: size=%u", GST_BUFFER_SIZE (buf));

  GST_LOG_OBJECT (self, "state: %d", 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_ports (self);

    g_omx_core_prepare (self->gomx);

    if (gomx->omx_state == OMX_StateIdle) {
      self->ready = TRUE;
      GST_INFO_OBJECT (self, "start srcpad task");
      gst_pad_start_task (self->srcpad, output_loop, self->srcpad);
    }

    g_mutex_unlock (self->ready_lock);

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

#ifdef ANDROID
  if (gomx->settings_changed) {
    GST_DEBUG_OBJECT (self, "settings changed called from streaming thread... Android");
    if (gomx->settings_changed_cb)
      gomx->settings_changed_cb (gomx);

    gomx->settings_changed = FALSE;
  }
#endif

  in_port = self->in_port;

  if (G_LIKELY (in_port->enabled)) {
    guint buffer_offset = 0;

    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 */
            /** @todo move to util */
      if (self->codec_data) {
        OMX_BUFFERHEADERTYPE *omx_buffer;

        GST_LOG_OBJECT (self, "request buffer");
        omx_buffer = g_omx_port_request_buffer (in_port);

        if (G_LIKELY (omx_buffer)) {
          omx_buffer->nFlags |= 0x00000080;     /* codec data flag */

          omx_buffer->nFilledLen = GST_BUFFER_SIZE (self->codec_data);
          memcpy (omx_buffer->pBuffer + omx_buffer->nOffset,
              GST_BUFFER_DATA (self->codec_data), omx_buffer->nFilledLen);

          GST_LOG_OBJECT (self, "release_buffer");
          g_omx_port_release_buffer (in_port, omx_buffer);
        }
      }
    }

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

    while (G_LIKELY (buffer_offset < GST_BUFFER_SIZE (buf))) {
      OMX_BUFFERHEADERTYPE *omx_buffer;

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

      GST_LOG_OBJECT (self, "request buffer");
      omx_buffer = g_omx_port_request_buffer (in_port);

      GST_LOG_OBJECT (self, "omx_buffer: %p", omx_buffer);

      if (G_LIKELY (omx_buffer)) {
        log_buffer (self, omx_buffer);

        if (omx_buffer->nOffset == 0 && self->share_input_buffer) {
          {
            GstBuffer *old_buf;
            old_buf = omx_buffer->pAppPrivate;

            if (old_buf) {
              gst_buffer_unref (old_buf);
            } else if (omx_buffer->pBuffer) {
              g_free (omx_buffer->pBuffer);
            }
          }

          omx_buffer->pBuffer = GST_BUFFER_DATA (buf);
          omx_buffer->nAllocLen = GST_BUFFER_SIZE (buf);
          omx_buffer->nFilledLen = GST_BUFFER_SIZE (buf);
          omx_buffer->pAppPrivate = buf;
        } else {
          omx_buffer->nFilledLen = MIN (GST_BUFFER_SIZE (buf) - buffer_offset,
              omx_buffer->nAllocLen - omx_buffer->nOffset);
          memcpy (omx_buffer->pBuffer + omx_buffer->nOffset,
              GST_BUFFER_DATA (buf) + buffer_offset, omx_buffer->nFilledLen);
        }

        if (self->use_timestamps) {
          GstClockTime timestamp_offset = 0;

          if (buffer_offset && GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) {
            timestamp_offset = gst_util_uint64_scale_int (buffer_offset,
                GST_BUFFER_DURATION (buf), GST_BUFFER_SIZE (buf));
          }

          omx_buffer->nTimeStamp =
              gst_util_uint64_scale_int (GST_BUFFER_TIMESTAMP (buf) +
              timestamp_offset, OMX_TICKS_PER_SECOND, GST_SECOND);
        }

        buffer_offset += omx_buffer->nFilledLen;
#ifdef ANDROID
        omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
        log_buffer (self, omx_buffer);
#endif

        GST_LOG_OBJECT (self, "release_buffer");
                /** @todo untaint buffer */
        g_omx_port_release_buffer (in_port, omx_buffer);
      } else {
        GST_WARNING_OBJECT (self, "null buffer");
        ret = GST_FLOW_WRONG_STATE;
        goto out_flushing;
      }
    }
  } else {
    GST_WARNING_OBJECT (self, "done");
    ret = GST_FLOW_UNEXPECTED;
  }

  if (!self->share_input_buffer) {
    gst_buffer_unref (buf);
  }

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), ("%s", error_msg));
      ret = GST_FLOW_ERROR;
    }

    gst_buffer_unref (buf);

    goto leave;
  }
}