Пример #1
0
/**
 * Utility function to handle transferring Gstreamer timestamp to OMX
 * timestamp.  This function handles discontinuities and timestamp
 * renormalization.
 *
 * @omx_buffer the destination OMX buffer for the timestamp
 * @buffer     the source Gstreamer buffer for the timestamp
 * @normalize  should this buffer be the one that we renormalize on
 *   (iff normalization is required)?  (ie. with TI OMX, you should
 *   only re-normalize on a video buffer)
 */
gboolean
gst_goo_timestamp_gst2omx (
		OMX_BUFFERHEADERTYPE* omx_buffer,
		GstBuffer* buffer,
		gboolean normalize)
{
	GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);

	if (GST_GOO_UTIL_IS_DISCONT (buffer))
	{
		needs_normalization = TRUE;
		GST_DEBUG ("needs_normalization");
	}

	if (needs_normalization && normalize)
	{
		GST_INFO ("Setting OMX_BUFFER_STARTTIME..");
		omx_buffer->nFlags |= OMX_BUFFERFLAG_STARTTIME;
		omx_normalize_timestamp = GST2OMX_TIMESTAMP ((gint64)timestamp);
		needs_normalization = FALSE;
		GST_DEBUG ("omx_normalize_timestamp=%lld", omx_normalize_timestamp);
	}

	/* transfer timestamp to openmax */
	if (GST_CLOCK_TIME_IS_VALID (timestamp))
	{
		omx_buffer->nTimeStamp = GST2OMX_TIMESTAMP ((gint64)timestamp) - omx_normalize_timestamp;
		GST_INFO ("OMX timestamp = %lld (%lld - %lld)", omx_buffer->nTimeStamp, GST2OMX_TIMESTAMP ((gint64)timestamp), omx_normalize_timestamp);
		return TRUE;
	}
	else
	{
		GST_WARNING ("Invalid timestamp!");
		return FALSE;
	}
}
Пример #2
0
static GstFlowReturn
gst_goo_encjpeg_chain (GstPad* pad, GstBuffer* buffer)
{
	GST_LOG ("");

	GstGooEncJpeg* self = GST_GOO_ENCJPEG (gst_pad_get_parent (pad));
	GstGooEncJpegPrivate* priv = GST_GOO_ENCJPEG_GET_PRIVATE (self);
	GstFlowReturn ret = GST_FLOW_OK;
	GstGooAdapter* adapter = self->adapter;
	OMX_BUFFERHEADERTYPE* omx_buffer = NULL;

	GstClockTime timestamp, duration;
	guint64 offset, offsetend;
	GstBuffer* outbuf = NULL;

	if (goo_port_is_tunneled (self->inport))
	{
		GST_INFO ("Inport is tunneled");
		ret = GST_FLOW_OK;
		priv->incount++;
		goto process_output;
	}

	if (goo_port_is_eos (self->inport))
	{
		GST_INFO ("port is eos");
		ret = GST_FLOW_UNEXPECTED;
		goto fail;
	}

	if (self->component->cur_state != OMX_StateExecuting)
	{
		goto fail;
	}

	/* let's copy the timestamp meta data */
	timestamp = GST_BUFFER_TIMESTAMP (buffer);
	duration  = GST_BUFFER_DURATION (buffer);
	offset	  = GST_BUFFER_OFFSET (buffer);
	offsetend = GST_BUFFER_OFFSET_END (buffer);

	if (GST_IS_GOO_BUFFER (buffer) &&
	    goo_port_is_my_buffer (self->inport,
				   GST_GOO_BUFFER (buffer)->omx_buffer))
	{
		GST_INFO ("My own OMX buffer");
		priv->incount++;
		gst_buffer_unref (buffer); /* let's push the buffer to omx */
		ret = GST_FLOW_OK;
	}
	else if (GST_IS_GOO_BUFFER (buffer) &&
		 !goo_port_is_my_buffer (self->inport,
					 GST_GOO_BUFFER (buffer)->omx_buffer))
	{
		GST_INFO ("Other OMX buffer");

		if (GST_BUFFER_SIZE (buffer) != priv->omxbufsiz)
		{
			GST_ELEMENT_ERROR (self, STREAM, FORMAT,
					   ("Frame is incomplete (%u!=%u)",
					    GST_BUFFER_SIZE (buffer),
					    priv->omxbufsiz),
					   ("Frame is incomplete (%u!=%u)",
					    GST_BUFFER_SIZE (buffer),
					    priv->omxbufsiz));
			ret = GST_FLOW_ERROR;
		}

		omx_buffer = goo_port_grab_buffer (self->inport);
		memcpy (omx_buffer->pBuffer, GST_BUFFER_DATA (buffer),
			priv->omxbufsiz);
		omx_buffer->nFilledLen = priv->omxbufsiz;
		priv->incount++;
		goo_component_release_buffer (self->component, omx_buffer);
		gst_buffer_unref (buffer);
		ret = GST_FLOW_OK;
	}
	else
	{
		if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
		{
			gst_goo_adapter_clear (adapter);
		}

		GST_LOG ("size = %d bytes", GST_BUFFER_SIZE (buffer));
		gst_goo_adapter_push (adapter, buffer);

		guint tmp = priv->incount;
		while (gst_goo_adapter_available (adapter) >= priv->omxbufsiz &&
		       ret == GST_FLOW_OK)
		{
			GST_DEBUG ("Pushing data to OMX");
			OMX_BUFFERHEADERTYPE* omx_buffer;
			omx_buffer = goo_port_grab_buffer (self->inport);
			gst_goo_adapter_peek (adapter, priv->omxbufsiz,
					      omx_buffer);
			omx_buffer->nFilledLen = priv->omxbufsiz;
			gst_goo_adapter_flush (adapter, priv->omxbufsiz);
			priv->incount++;
			goo_component_release_buffer (self->component,
						      omx_buffer);
			ret = GST_FLOW_OK;
		}

		if (tmp == priv->incount)
		{
			goto done;
		}
	}

process_output:
	if (goo_port_is_tunneled (self->outport))
	{
		outbuf = gst_ghost_buffer_new ();
		GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_READONLY);
		GST_BUFFER_DATA (outbuf)       = NULL;
		GST_BUFFER_SIZE (outbuf)       = 0;
		GST_BUFFER_TIMESTAMP (outbuf)  = timestamp;
		GST_BUFFER_DURATION (outbuf)   = duration;
		GST_BUFFER_OFFSET (outbuf)     = offset;
		GST_BUFFER_OFFSET_END (outbuf) = offsetend;
		gst_buffer_set_caps (outbuf, GST_PAD_CAPS (self->srcpad));
		gst_pad_push (self->srcpad, outbuf);
		goto done;
	}

	GST_DEBUG ("Poping out buffer from OMX");
	omx_buffer = goo_port_grab_buffer (self->outport);

	if (omx_buffer->nFilledLen <= 0)
	{
		ret = GST_FLOW_ERROR;
		goto done;
	}

	if (gst_pad_alloc_buffer (self->srcpad, priv->outcount,
				  omx_buffer->nFilledLen,
				  GST_PAD_CAPS (self->srcpad),
				  &outbuf) == GST_FLOW_OK)
	{
		priv->outcount++;

		/* if the buffer is a goo buffer of the peer element */
		if (GST_IS_GOO_BUFFER (outbuf))
		{
			GST_INFO ("It is a OMX buffer!");
			memcpy (GST_GOO_BUFFER (outbuf)->omx_buffer->pBuffer,
				omx_buffer->pBuffer, omx_buffer->nFilledLen);
			GST_GOO_BUFFER (outbuf)->omx_buffer->nFilledLen =
				omx_buffer->nFilledLen;
			GST_GOO_BUFFER (outbuf)->omx_buffer->nFlags =
				omx_buffer->nFlags;
			GST_GOO_BUFFER (outbuf)->omx_buffer->nTimeStamp =
				GST2OMX_TIMESTAMP (timestamp);
			goo_component_release_buffer (self->component,
						      omx_buffer);
		}
		else
		{
			/* @fixme! */
			/* we do this because there is a buffer extarbation
			 * when a filesink is used.
			 * Maybe using multiple buffers it could be solved.
			 */
			memcpy (GST_BUFFER_DATA (outbuf),
				omx_buffer->pBuffer, omx_buffer->nFilledLen);
			goo_component_release_buffer (self->component,
						      omx_buffer);

/* 			gst_buffer_unref (outbuf); */
/* 			outbuf = GST_BUFFER (gst_goo_buffer_new ()); */
/* 			gst_goo_buffer_set_data (outbuf, */
/* 						 self->component, */
/* 						 omx_buffer); */
		}

		GST_BUFFER_TIMESTAMP (outbuf)  = timestamp;
		GST_BUFFER_DURATION (outbuf)   = duration;
		GST_BUFFER_OFFSET (outbuf)     = offset;
		GST_BUFFER_OFFSET_END (outbuf) = offsetend;

		gst_buffer_set_caps (outbuf, GST_PAD_CAPS (self->srcpad));
		g_signal_emit (G_OBJECT (self),
			       gst_goo_encjpeg_signals[FRAME_ENCODED], 0);
	
		ret = gst_pad_push (self->srcpad, outbuf);
		if (omx_buffer->nFlags & OMX_BUFFERFLAG_EOS ||
		   	goo_port_is_eos (self->outport))
		{
			GST_INFO ("EOS flag found in output buffer (%d)",
			  	omx_buffer->nFilledLen);
			goo_component_set_done (self->component);

		}

		goto done;
	}
	else
	{
		ret = GST_FLOW_ERROR;
		goto done;
	}

fail:
	gst_buffer_unref (buffer);
	gst_goo_adapter_clear (adapter);

done:
	gst_object_unref (self);
	return ret;

}