mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 23:18:52 +00:00
gst/base/gstbasetransform.*: Make passthrough work using the bufferpools.
Original commit message from CVS: * gst/base/gstbasetransform.c: (gst_base_transform_init), (gst_base_transform_transform_caps), (gst_base_transform_getcaps), (gst_base_transform_configure_caps), (gst_base_transform_setcaps), (gst_base_transform_get_size), (gst_base_transform_buffer_alloc), (gst_base_transform_handle_buffer), (gst_base_transform_getrange), (gst_base_transform_chain), (gst_base_transform_change_state), (gst_base_transform_set_passthrough), (gst_base_transform_is_passthrough): * gst/base/gstbasetransform.h: Make passthrough work using the bufferpools. Changed API a bit, subclasses have to write into a buffer provided by the base class. More debug info in nego functions. * gst/elements/gstidentity.c: (gst_identity_init), (gst_identity_transform): Port to new base class.
This commit is contained in:
parent
a8d8310819
commit
7f4581d977
7 changed files with 658 additions and 128 deletions
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
||||||
|
2005-07-15 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* gst/base/gstbasetransform.c: (gst_base_transform_init),
|
||||||
|
(gst_base_transform_transform_caps), (gst_base_transform_getcaps),
|
||||||
|
(gst_base_transform_configure_caps), (gst_base_transform_setcaps),
|
||||||
|
(gst_base_transform_get_size), (gst_base_transform_buffer_alloc),
|
||||||
|
(gst_base_transform_handle_buffer), (gst_base_transform_getrange),
|
||||||
|
(gst_base_transform_chain), (gst_base_transform_change_state),
|
||||||
|
(gst_base_transform_set_passthrough),
|
||||||
|
(gst_base_transform_is_passthrough):
|
||||||
|
* gst/base/gstbasetransform.h:
|
||||||
|
Make passthrough work using the bufferpools.
|
||||||
|
Changed API a bit, subclasses have to write into a buffer
|
||||||
|
provided by the base class.
|
||||||
|
More debug info in nego functions.
|
||||||
|
|
||||||
|
* gst/elements/gstidentity.c: (gst_identity_init),
|
||||||
|
(gst_identity_transform):
|
||||||
|
Port to new base class.
|
||||||
|
|
||||||
2005-07-15 Wim Taymans <wim@fluendo.com>
|
2005-07-15 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst/gstmessage.c: (gst_message_new_state_changed):
|
* gst/gstmessage.c: (gst_message_new_state_changed):
|
||||||
|
|
|
@ -88,6 +88,8 @@ static gboolean gst_base_transform_src_activate_pull (GstPad * pad,
|
||||||
gboolean active);
|
gboolean active);
|
||||||
static gboolean gst_base_transform_sink_activate_push (GstPad * pad,
|
static gboolean gst_base_transform_sink_activate_push (GstPad * pad,
|
||||||
gboolean active);
|
gboolean active);
|
||||||
|
static guint gst_base_transform_get_size (GstBaseTransform * trans);
|
||||||
|
|
||||||
static GstElementStateReturn gst_base_transform_change_state (GstElement *
|
static GstElementStateReturn gst_base_transform_change_state (GstElement *
|
||||||
element);
|
element);
|
||||||
|
|
||||||
|
@ -96,10 +98,10 @@ static GstFlowReturn gst_base_transform_getrange (GstPad * pad, guint64 offset,
|
||||||
guint length, GstBuffer ** buffer);
|
guint length, GstBuffer ** buffer);
|
||||||
static GstFlowReturn gst_base_transform_chain (GstPad * pad,
|
static GstFlowReturn gst_base_transform_chain (GstPad * pad,
|
||||||
GstBuffer * buffer);
|
GstBuffer * buffer);
|
||||||
static GstFlowReturn gst_base_transform_handle_buffer (GstBaseTransform * trans,
|
|
||||||
GstBuffer * inbuf, GstBuffer ** outbuf);
|
|
||||||
static GstCaps *gst_base_transform_getcaps (GstPad * pad);
|
static GstCaps *gst_base_transform_getcaps (GstPad * pad);
|
||||||
static gboolean gst_base_transform_setcaps (GstPad * pad, GstCaps * caps);
|
static gboolean gst_base_transform_setcaps (GstPad * pad, GstCaps * caps);
|
||||||
|
static GstFlowReturn gst_base_transform_buffer_alloc (GstPad * pad,
|
||||||
|
guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
|
||||||
|
|
||||||
/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
|
/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
|
||||||
|
|
||||||
|
@ -159,6 +161,8 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_chain));
|
GST_DEBUG_FUNCPTR (gst_base_transform_chain));
|
||||||
gst_pad_set_activatepush_function (trans->sinkpad,
|
gst_pad_set_activatepush_function (trans->sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_push));
|
GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_push));
|
||||||
|
gst_pad_set_bufferalloc_function (trans->sinkpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_base_transform_buffer_alloc));
|
||||||
gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad);
|
gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad);
|
||||||
|
|
||||||
pad_template =
|
pad_template =
|
||||||
|
@ -174,6 +178,8 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
||||||
gst_pad_set_activatepull_function (trans->srcpad,
|
gst_pad_set_activatepull_function (trans->srcpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_pull));
|
GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_pull));
|
||||||
gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
|
gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
|
||||||
|
|
||||||
|
trans->passthrough = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
|
@ -187,10 +193,31 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad,
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (trans, "from: %" GST_PTR_FORMAT, caps);
|
GST_DEBUG_OBJECT (trans, "from: %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
if (klass->transform_caps)
|
/* if there is a custom transform function, use this */
|
||||||
ret = klass->transform_caps (trans, pad, caps);
|
if (klass->transform_caps) {
|
||||||
else
|
GstCaps *temp;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
ret = gst_caps_new_empty ();
|
||||||
|
|
||||||
|
/* we send caps with just one structure to the transform
|
||||||
|
* function as this is easier for the element */
|
||||||
|
for (i = 0; i < gst_caps_get_size (caps); i++) {
|
||||||
|
GstCaps *nth;
|
||||||
|
|
||||||
|
nth = gst_caps_copy_nth (caps, i);
|
||||||
|
GST_DEBUG_OBJECT (trans, " from: %" GST_PTR_FORMAT, nth);
|
||||||
|
temp = klass->transform_caps (trans, pad, nth);
|
||||||
|
gst_caps_unref (nth);
|
||||||
|
GST_DEBUG_OBJECT (trans, " to : %" GST_PTR_FORMAT, temp);
|
||||||
|
|
||||||
|
gst_caps_append (ret, temp);
|
||||||
|
}
|
||||||
|
gst_caps_do_simplify (ret);
|
||||||
|
} else {
|
||||||
|
/* else use the identity transform */
|
||||||
ret = gst_caps_ref (caps);
|
ret = gst_caps_ref (caps);
|
||||||
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (trans, "to: %" GST_PTR_FORMAT, ret);
|
GST_DEBUG_OBJECT (trans, "to: %" GST_PTR_FORMAT, ret);
|
||||||
|
|
||||||
|
@ -210,25 +237,66 @@ gst_base_transform_getcaps (GstPad * pad)
|
||||||
|
|
||||||
/* we can do what the peer can */
|
/* we can do what the peer can */
|
||||||
caps = gst_pad_peer_get_caps (otherpad);
|
caps = gst_pad_peer_get_caps (otherpad);
|
||||||
|
|
||||||
if (caps) {
|
if (caps) {
|
||||||
GstCaps *temp;
|
GstCaps *temp;
|
||||||
|
const GstCaps *templ;
|
||||||
|
|
||||||
temp = gst_caps_intersect (caps, gst_pad_get_pad_template_caps (otherpad));
|
GST_DEBUG ("peer caps %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
|
/* filtered against our padtemplate */
|
||||||
|
templ = gst_pad_get_pad_template_caps (otherpad);
|
||||||
|
GST_DEBUG ("our template %" GST_PTR_FORMAT, templ);
|
||||||
|
temp = gst_caps_intersect (caps, templ);
|
||||||
|
GST_DEBUG ("intersected %" GST_PTR_FORMAT, temp);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
|
/* then see what we can tranform this to */
|
||||||
caps = gst_base_transform_transform_caps (trans, otherpad, temp);
|
caps = gst_base_transform_transform_caps (trans, otherpad, temp);
|
||||||
|
GST_DEBUG ("transformed %" GST_PTR_FORMAT, caps);
|
||||||
gst_caps_unref (temp);
|
gst_caps_unref (temp);
|
||||||
temp = gst_caps_intersect (caps, gst_pad_get_pad_template_caps (pad));
|
if (caps == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* and filter against the template again */
|
||||||
|
templ = gst_pad_get_pad_template_caps (pad);
|
||||||
|
GST_DEBUG ("our template %" GST_PTR_FORMAT, templ);
|
||||||
|
temp = gst_caps_intersect (caps, templ);
|
||||||
|
GST_DEBUG ("intersected %" GST_PTR_FORMAT, temp);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
|
/* this is what we can do */
|
||||||
caps = temp;
|
caps = temp;
|
||||||
} else {
|
} else {
|
||||||
/* no peer, our padtemplate is enough then */
|
/* no peer, our padtemplate is enough then */
|
||||||
caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
|
caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
GST_DEBUG ("returning %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_base_transform_configure_caps (GstBaseTransform * trans, GstCaps * in,
|
||||||
|
GstCaps * out)
|
||||||
|
{
|
||||||
|
gboolean ret = TRUE;
|
||||||
|
GstBaseTransformClass *klass;
|
||||||
|
|
||||||
|
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
|
||||||
|
/* no configure the element with the caps */
|
||||||
|
if (klass->set_caps) {
|
||||||
|
ret = klass->set_caps (trans, in, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if all goes well, get the size of the output buffer */
|
||||||
|
if (ret) {
|
||||||
|
trans->out_size = gst_base_transform_get_size (trans);
|
||||||
|
GST_DEBUG ("output buffer size %d", trans->out_size);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
|
@ -252,11 +320,9 @@ gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
/* see how we can transform the input caps */
|
/* see how we can transform the input caps */
|
||||||
othercaps = gst_base_transform_transform_caps (trans, pad, caps);
|
othercaps = gst_base_transform_transform_caps (trans, pad, caps);
|
||||||
|
|
||||||
if (!othercaps || gst_caps_is_empty (othercaps)) {
|
/* check if transform is empty */
|
||||||
GST_DEBUG ("transform returned useless %" GST_PTR_FORMAT, othercaps);
|
if (!othercaps || gst_caps_is_empty (othercaps))
|
||||||
ret = FALSE;
|
goto no_transform;
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gst_caps_is_fixed (othercaps)) {
|
if (!gst_caps_is_fixed (othercaps)) {
|
||||||
GstCaps *temp;
|
GstCaps *temp;
|
||||||
|
@ -266,7 +332,7 @@ gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
temp = gst_caps_intersect (othercaps, caps);
|
temp = gst_caps_intersect (othercaps, caps);
|
||||||
GST_DEBUG ("intersect returned %" GST_PTR_FORMAT, temp);
|
GST_DEBUG ("intersect returned %" GST_PTR_FORMAT, temp);
|
||||||
if (temp) {
|
if (temp) {
|
||||||
if (!gst_caps_is_empty (temp)) {
|
if (!gst_caps_is_empty (temp) && otherpeer) {
|
||||||
GST_DEBUG ("try passthrough with %" GST_PTR_FORMAT, caps);
|
GST_DEBUG ("try passthrough with %" GST_PTR_FORMAT, caps);
|
||||||
/* try passthrough. we know it's fixed, because caps is fixed */
|
/* try passthrough. we know it's fixed, because caps is fixed */
|
||||||
if (gst_pad_accept_caps (otherpeer, caps)) {
|
if (gst_pad_accept_caps (otherpeer, caps)) {
|
||||||
|
@ -312,39 +378,99 @@ gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
GST_DEBUG ("after fixating %" GST_PTR_FORMAT, othercaps);
|
GST_DEBUG ("after fixating %" GST_PTR_FORMAT, othercaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_return_val_if_fail (gst_caps_is_fixed (othercaps), FALSE);
|
/* caps should be fixed now */
|
||||||
|
if (!gst_caps_is_fixed (othercaps))
|
||||||
|
goto could_not_fixate;
|
||||||
|
|
||||||
if (otherpeer && !gst_pad_accept_caps (otherpeer, othercaps)) {
|
/* and peer should accept */
|
||||||
GST_DEBUG ("FAILED to get peer of %" GST_PTR_FORMAT
|
if (otherpeer && !gst_pad_accept_caps (otherpeer, othercaps))
|
||||||
" to accept %" GST_PTR_FORMAT, otherpad, othercaps);
|
goto peer_no_accept;
|
||||||
ret = FALSE;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG ("got final caps %" GST_PTR_FORMAT, othercaps);
|
GST_DEBUG ("got final caps %" GST_PTR_FORMAT, othercaps);
|
||||||
|
|
||||||
/* we know this will work, we implement the setcaps */
|
/* we know this will work, we implement the setcaps */
|
||||||
gst_pad_set_caps (otherpad, othercaps);
|
gst_pad_set_caps (otherpad, othercaps);
|
||||||
|
|
||||||
/* success, let the element know */
|
trans->in_place = gst_caps_is_equal (caps, othercaps);
|
||||||
if (klass->set_caps) {
|
GST_DEBUG ("in_place: %d", trans->in_place);
|
||||||
|
|
||||||
|
/* see if we have to configure the element now */
|
||||||
|
if (!trans->delay_configure) {
|
||||||
if (pad == trans->sinkpad)
|
if (pad == trans->sinkpad)
|
||||||
ret = klass->set_caps (trans, caps, othercaps);
|
ret = gst_base_transform_configure_caps (trans, caps, othercaps);
|
||||||
else
|
else
|
||||||
ret = klass->set_caps (trans, othercaps, caps);
|
ret = gst_base_transform_configure_caps (trans, othercaps, caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
if (otherpeer)
|
if (otherpeer)
|
||||||
gst_object_unref (otherpeer);
|
gst_object_unref (otherpeer);
|
||||||
|
|
||||||
if (othercaps)
|
if (othercaps)
|
||||||
gst_caps_unref (othercaps);
|
gst_caps_unref (othercaps);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_transform:
|
||||||
|
{
|
||||||
|
GST_DEBUG ("transform returned useless %" GST_PTR_FORMAT, othercaps);
|
||||||
|
ret = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
could_not_fixate:
|
||||||
|
{
|
||||||
|
GST_DEBUG ("FAILED to fixate %" GST_PTR_FORMAT, othercaps);
|
||||||
|
ret = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
peer_no_accept:
|
||||||
|
{
|
||||||
|
GST_DEBUG ("FAILED to get peer of %" GST_PTR_FORMAT
|
||||||
|
" to accept %" GST_PTR_FORMAT, otherpad, othercaps);
|
||||||
|
ret = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guint
|
||||||
|
gst_base_transform_get_size (GstBaseTransform * trans)
|
||||||
|
{
|
||||||
|
guint res = -1;
|
||||||
|
GstBaseTransformClass *bclass;
|
||||||
|
|
||||||
|
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
if (bclass->get_size) {
|
||||||
|
res = bclass->get_size (trans);
|
||||||
|
GST_DEBUG ("get size function returned %d", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
|
||||||
|
GstCaps * caps, GstBuffer ** buf)
|
||||||
|
{
|
||||||
|
GstBaseTransform *trans;
|
||||||
|
GstFlowReturn res;
|
||||||
|
|
||||||
|
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
|
if (trans->in_place) {
|
||||||
|
/* we can only proxy the bufferpool if we do in_place transforms */
|
||||||
|
res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);
|
||||||
|
} else {
|
||||||
|
/* else let the default alloc function allocate a buffer */
|
||||||
|
*buf = NULL;
|
||||||
|
res = GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_object_unref (trans);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_base_transform_event (GstPad * pad, GstEvent * event)
|
gst_base_transform_event (GstPad * pad, GstEvent * event)
|
||||||
{
|
{
|
||||||
|
@ -382,6 +508,92 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
|
GstBuffer ** outbuf)
|
||||||
|
{
|
||||||
|
GstBaseTransformClass *bclass;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
|
||||||
|
if (trans->in_place) {
|
||||||
|
if (bclass->transform_ip) {
|
||||||
|
gst_buffer_ref (inbuf);
|
||||||
|
|
||||||
|
/* in place transform and subclass supports method */
|
||||||
|
ret = bclass->transform_ip (trans, inbuf);
|
||||||
|
|
||||||
|
*outbuf = inbuf;
|
||||||
|
} else {
|
||||||
|
/* in place transform and subclass does not support method */
|
||||||
|
if (bclass->transform) {
|
||||||
|
/* make a copy of the buffer */
|
||||||
|
*outbuf = inbuf;
|
||||||
|
inbuf = gst_buffer_copy (inbuf);
|
||||||
|
|
||||||
|
ret = bclass->transform (trans, inbuf, *outbuf);
|
||||||
|
} else {
|
||||||
|
ret = GST_FLOW_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* figure out the output size */
|
||||||
|
if (trans->out_size == -1) {
|
||||||
|
/* ask subclass */
|
||||||
|
if ((trans->out_size = gst_base_transform_get_size (trans)) == -1)
|
||||||
|
/* else we have an error */
|
||||||
|
goto no_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we cannot reconfigure the element yet as we are still processing
|
||||||
|
* the old buffer. We will therefore delay the reconfiguration of the
|
||||||
|
* element until we have processed this last buffer. */
|
||||||
|
trans->delay_configure = TRUE;
|
||||||
|
|
||||||
|
/* no in place transform, get buffer, this might renegotiate. */
|
||||||
|
ret = gst_pad_alloc_buffer (trans->srcpad,
|
||||||
|
GST_BUFFER_OFFSET (inbuf), trans->out_size,
|
||||||
|
GST_PAD_CAPS (trans->srcpad), outbuf);
|
||||||
|
|
||||||
|
trans->delay_configure = FALSE;
|
||||||
|
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
goto no_buffer;
|
||||||
|
|
||||||
|
gst_buffer_stamp (*outbuf, inbuf);
|
||||||
|
|
||||||
|
if (bclass->transform)
|
||||||
|
ret = bclass->transform (trans, inbuf, *outbuf);
|
||||||
|
else
|
||||||
|
ret = GST_FLOW_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
ret =
|
||||||
|
gst_base_transform_configure_caps (trans,
|
||||||
|
GST_PAD_CAPS (trans->sinkpad), GST_PAD_CAPS (trans->srcpad));
|
||||||
|
}
|
||||||
|
gst_buffer_unref (inbuf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_size:
|
||||||
|
{
|
||||||
|
gst_buffer_unref (inbuf);
|
||||||
|
GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
|
||||||
|
("subclass did not specify output size"),
|
||||||
|
("subclass did not specify output size"));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
no_buffer:
|
||||||
|
{
|
||||||
|
gst_buffer_unref (inbuf);
|
||||||
|
GST_DEBUG ("could not get buffer from pool");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_base_transform_getrange (GstPad * pad, guint64 offset,
|
gst_base_transform_getrange (GstPad * pad, guint64 offset,
|
||||||
guint length, GstBuffer ** buffer)
|
guint length, GstBuffer ** buffer)
|
||||||
|
@ -390,16 +602,14 @@ gst_base_transform_getrange (GstPad * pad, guint64 offset,
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
GstBuffer *inbuf;
|
GstBuffer *inbuf;
|
||||||
|
|
||||||
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
|
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
GST_STREAM_LOCK (pad);
|
|
||||||
|
|
||||||
ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf);
|
ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf);
|
||||||
if (ret == GST_FLOW_OK) {
|
if (ret == GST_FLOW_OK) {
|
||||||
ret = gst_base_transform_handle_buffer (trans, inbuf, buffer);
|
ret = gst_base_transform_handle_buffer (trans, inbuf, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_STREAM_UNLOCK (pad);
|
gst_object_unref (trans);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -408,33 +618,17 @@ static GstFlowReturn
|
||||||
gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
|
gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstBaseTransform *trans;
|
GstBaseTransform *trans;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret;
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
|
|
||||||
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
|
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
GST_STREAM_LOCK (pad);
|
|
||||||
|
|
||||||
ret = gst_base_transform_handle_buffer (trans, buffer, &outbuf);
|
ret = gst_base_transform_handle_buffer (trans, buffer, &outbuf);
|
||||||
if (ret == GST_FLOW_OK) {
|
if (ret == GST_FLOW_OK) {
|
||||||
ret = gst_pad_push (trans->srcpad, outbuf);
|
ret = gst_pad_push (trans->srcpad, outbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_STREAM_UNLOCK (pad);
|
gst_object_unref (trans);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
|
|
||||||
GstBuffer ** outbuf)
|
|
||||||
{
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
|
||||||
GstBaseTransformClass *bclass;
|
|
||||||
|
|
||||||
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
|
||||||
if (bclass->transform)
|
|
||||||
ret = bclass->transform (trans, inbuf, outbuf);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -524,6 +718,10 @@ gst_base_transform_change_state (GstElement * element)
|
||||||
case GST_STATE_NULL_TO_READY:
|
case GST_STATE_NULL_TO_READY:
|
||||||
break;
|
break;
|
||||||
case GST_STATE_READY_TO_PAUSED:
|
case GST_STATE_READY_TO_PAUSED:
|
||||||
|
GST_LOCK (trans);
|
||||||
|
trans->in_place = trans->passthrough;
|
||||||
|
trans->out_size = -1;
|
||||||
|
GST_UNLOCK (trans);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_PAUSED_TO_PLAYING:
|
case GST_STATE_PAUSED_TO_PLAYING:
|
||||||
break;
|
break;
|
||||||
|
@ -548,3 +746,48 @@ gst_base_transform_change_state (GstElement * element)
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_base_transform_set_passthrough:
|
||||||
|
* @trans: the #GstBaseTransform to set
|
||||||
|
* @passthrough: boolean indicating passthrough mode.
|
||||||
|
*
|
||||||
|
* Set passthrough mode for this filter by default. This is mostly
|
||||||
|
* usefull for filters that do not care about negotiation.
|
||||||
|
*
|
||||||
|
* MT safe.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_base_transform_set_passthrough (GstBaseTransform * trans,
|
||||||
|
gboolean passthrough)
|
||||||
|
{
|
||||||
|
g_return_if_fail (trans != NULL);
|
||||||
|
|
||||||
|
GST_LOCK (trans);
|
||||||
|
trans->passthrough = passthrough;
|
||||||
|
GST_UNLOCK (trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_base_transform_is_passthrough:
|
||||||
|
* @trans: the #GstBaseTransform to query
|
||||||
|
*
|
||||||
|
* See if @trans is configured as a passthrough transform.
|
||||||
|
*
|
||||||
|
* Returns: TRUE is the transform is configured in passthrough mode.
|
||||||
|
*
|
||||||
|
* MT safe.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_base_transform_is_passthrough (GstBaseTransform * trans)
|
||||||
|
{
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
|
g_return_val_if_fail (trans != NULL, FALSE);
|
||||||
|
|
||||||
|
GST_LOCK (trans);
|
||||||
|
result = trans->passthrough;
|
||||||
|
GST_UNLOCK (trans);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,12 @@ struct _GstBaseTransform {
|
||||||
/* source and sink pads */
|
/* source and sink pads */
|
||||||
GstPad *sinkpad;
|
GstPad *sinkpad;
|
||||||
GstPad *srcpad;
|
GstPad *srcpad;
|
||||||
|
|
||||||
|
gboolean passthrough;
|
||||||
|
|
||||||
|
gboolean in_place;
|
||||||
|
guint out_size;
|
||||||
|
gboolean delay_configure;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstBaseTransformClass {
|
struct _GstBaseTransformClass {
|
||||||
|
@ -65,6 +71,9 @@ struct _GstBaseTransformClass {
|
||||||
gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *incaps,
|
gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *incaps,
|
||||||
GstCaps *outcaps);
|
GstCaps *outcaps);
|
||||||
|
|
||||||
|
/* get the size of the output buffer, -1 on error */
|
||||||
|
guint (*get_size) (GstBaseTransform *trans);
|
||||||
|
|
||||||
/* start and stop processing, ideal for opening/closing the resource */
|
/* start and stop processing, ideal for opening/closing the resource */
|
||||||
gboolean (*start) (GstBaseTransform *trans);
|
gboolean (*start) (GstBaseTransform *trans);
|
||||||
gboolean (*stop) (GstBaseTransform *trans);
|
gboolean (*stop) (GstBaseTransform *trans);
|
||||||
|
@ -73,9 +82,15 @@ struct _GstBaseTransformClass {
|
||||||
|
|
||||||
/* transform one incoming buffer to one outgoing buffer */
|
/* transform one incoming buffer to one outgoing buffer */
|
||||||
GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf,
|
GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf,
|
||||||
GstBuffer **outbuf);
|
GstBuffer *outbuf);
|
||||||
|
|
||||||
|
/* transform a buffer inplace */
|
||||||
|
GstFlowReturn (*transform_ip) (GstBaseTransform *trans, GstBuffer *buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void gst_base_transform_set_passthrough (GstBaseTransform *trans, gboolean passthrough);
|
||||||
|
gboolean gst_base_transform_is_passthrough (GstBaseTransform *trans);
|
||||||
|
|
||||||
GType gst_base_transform_get_type (void);
|
GType gst_base_transform_get_type (void);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -98,7 +98,7 @@ static void gst_identity_get_property (GObject * object, guint prop_id,
|
||||||
|
|
||||||
static gboolean gst_identity_event (GstBaseTransform * trans, GstEvent * event);
|
static gboolean gst_identity_event (GstBaseTransform * trans, GstEvent * event);
|
||||||
static GstFlowReturn gst_identity_transform (GstBaseTransform * trans,
|
static GstFlowReturn gst_identity_transform (GstBaseTransform * trans,
|
||||||
GstBuffer * inbuf, GstBuffer ** outbuf);
|
GstBuffer * inbuf, GstBuffer * outbuf);
|
||||||
static gboolean gst_identity_start (GstBaseTransform * trans);
|
static gboolean gst_identity_start (GstBaseTransform * trans);
|
||||||
static gboolean gst_identity_stop (GstBaseTransform * trans);
|
static gboolean gst_identity_stop (GstBaseTransform * trans);
|
||||||
|
|
||||||
|
@ -190,6 +190,8 @@ gst_identity_class_init (GstIdentityClass * klass)
|
||||||
static void
|
static void
|
||||||
gst_identity_init (GstIdentity * identity)
|
gst_identity_init (GstIdentity * identity)
|
||||||
{
|
{
|
||||||
|
gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (identity), TRUE);
|
||||||
|
|
||||||
identity->sleep_time = DEFAULT_SLEEP_TIME;
|
identity->sleep_time = DEFAULT_SLEEP_TIME;
|
||||||
identity->error_after = DEFAULT_ERROR_AFTER;
|
identity->error_after = DEFAULT_ERROR_AFTER;
|
||||||
identity->drop_probability = DEFAULT_DROP_PROBABILITY;
|
identity->drop_probability = DEFAULT_DROP_PROBABILITY;
|
||||||
|
@ -261,7 +263,7 @@ gst_identity_check_perfect (GstIdentity * identity, GstBuffer * buf)
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
GstBuffer ** outbuf)
|
GstBuffer * outbuf)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstIdentity *identity = GST_IDENTITY (trans);
|
GstIdentity *identity = GST_IDENTITY (trans);
|
||||||
|
@ -274,7 +276,6 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
if (identity->error_after == 0) {
|
if (identity->error_after == 0) {
|
||||||
GST_ELEMENT_ERROR (identity, CORE, FAILED,
|
GST_ELEMENT_ERROR (identity, CORE, FAILED,
|
||||||
(_("Failed after iterations as requested.")), (NULL));
|
(_("Failed after iterations as requested.")), (NULL));
|
||||||
gst_buffer_unref (inbuf);
|
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,7 +295,6 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
GST_BUFFER_FLAGS (inbuf), inbuf);
|
GST_BUFFER_FLAGS (inbuf), inbuf);
|
||||||
GST_UNLOCK (identity);
|
GST_UNLOCK (identity);
|
||||||
g_object_notify (G_OBJECT (identity), "last-message");
|
g_object_notify (G_OBJECT (identity), "last-message");
|
||||||
gst_buffer_unref (inbuf);
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,19 +319,16 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
g_object_notify (G_OBJECT (identity), "last-message");
|
g_object_notify (G_OBJECT (identity), "last-message");
|
||||||
}
|
}
|
||||||
|
|
||||||
*outbuf = gst_buffer_make_writable (inbuf);
|
|
||||||
/* inbuf is no longer usable */
|
|
||||||
|
|
||||||
if (identity->datarate > 0) {
|
if (identity->datarate > 0) {
|
||||||
GstClockTime time = identity->offset * GST_SECOND / identity->datarate;
|
GstClockTime time = identity->offset * GST_SECOND / identity->datarate;
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (*outbuf) = time;
|
GST_BUFFER_TIMESTAMP (outbuf) = time;
|
||||||
GST_BUFFER_DURATION (*outbuf) =
|
GST_BUFFER_DURATION (outbuf) =
|
||||||
GST_BUFFER_SIZE (*outbuf) * GST_SECOND / identity->datarate;
|
GST_BUFFER_SIZE (outbuf) * GST_SECOND / identity->datarate;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
|
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
|
||||||
*outbuf);
|
outbuf);
|
||||||
|
|
||||||
if (identity->sync) {
|
if (identity->sync) {
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
|
@ -344,7 +341,7 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
/* FIXME: actually unlock this somewhere if the state changes */
|
/* FIXME: actually unlock this somewhere if the state changes */
|
||||||
GST_LOCK (identity);
|
GST_LOCK (identity);
|
||||||
identity->clock_id = gst_clock_new_single_shot_id (clock,
|
identity->clock_id = gst_clock_new_single_shot_id (clock,
|
||||||
GST_BUFFER_TIMESTAMP (*outbuf) + GST_ELEMENT (identity)->base_time);
|
GST_BUFFER_TIMESTAMP (outbuf) + GST_ELEMENT (identity)->base_time);
|
||||||
GST_UNLOCK (identity);
|
GST_UNLOCK (identity);
|
||||||
cret = gst_clock_id_wait (identity->clock_id, NULL);
|
cret = gst_clock_id_wait (identity->clock_id, NULL);
|
||||||
GST_LOCK (identity);
|
GST_LOCK (identity);
|
||||||
|
@ -358,7 +355,7 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
identity->offset += GST_BUFFER_SIZE (*outbuf);
|
identity->offset += GST_BUFFER_SIZE (outbuf);
|
||||||
|
|
||||||
if (identity->sleep_time && ret == GST_FLOW_OK)
|
if (identity->sleep_time && ret == GST_FLOW_OK)
|
||||||
g_usleep (identity->sleep_time);
|
g_usleep (identity->sleep_time);
|
||||||
|
|
|
@ -88,6 +88,8 @@ static gboolean gst_base_transform_src_activate_pull (GstPad * pad,
|
||||||
gboolean active);
|
gboolean active);
|
||||||
static gboolean gst_base_transform_sink_activate_push (GstPad * pad,
|
static gboolean gst_base_transform_sink_activate_push (GstPad * pad,
|
||||||
gboolean active);
|
gboolean active);
|
||||||
|
static guint gst_base_transform_get_size (GstBaseTransform * trans);
|
||||||
|
|
||||||
static GstElementStateReturn gst_base_transform_change_state (GstElement *
|
static GstElementStateReturn gst_base_transform_change_state (GstElement *
|
||||||
element);
|
element);
|
||||||
|
|
||||||
|
@ -96,10 +98,10 @@ static GstFlowReturn gst_base_transform_getrange (GstPad * pad, guint64 offset,
|
||||||
guint length, GstBuffer ** buffer);
|
guint length, GstBuffer ** buffer);
|
||||||
static GstFlowReturn gst_base_transform_chain (GstPad * pad,
|
static GstFlowReturn gst_base_transform_chain (GstPad * pad,
|
||||||
GstBuffer * buffer);
|
GstBuffer * buffer);
|
||||||
static GstFlowReturn gst_base_transform_handle_buffer (GstBaseTransform * trans,
|
|
||||||
GstBuffer * inbuf, GstBuffer ** outbuf);
|
|
||||||
static GstCaps *gst_base_transform_getcaps (GstPad * pad);
|
static GstCaps *gst_base_transform_getcaps (GstPad * pad);
|
||||||
static gboolean gst_base_transform_setcaps (GstPad * pad, GstCaps * caps);
|
static gboolean gst_base_transform_setcaps (GstPad * pad, GstCaps * caps);
|
||||||
|
static GstFlowReturn gst_base_transform_buffer_alloc (GstPad * pad,
|
||||||
|
guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
|
||||||
|
|
||||||
/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
|
/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
|
||||||
|
|
||||||
|
@ -159,6 +161,8 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_chain));
|
GST_DEBUG_FUNCPTR (gst_base_transform_chain));
|
||||||
gst_pad_set_activatepush_function (trans->sinkpad,
|
gst_pad_set_activatepush_function (trans->sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_push));
|
GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_push));
|
||||||
|
gst_pad_set_bufferalloc_function (trans->sinkpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_base_transform_buffer_alloc));
|
||||||
gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad);
|
gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad);
|
||||||
|
|
||||||
pad_template =
|
pad_template =
|
||||||
|
@ -174,6 +178,8 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
||||||
gst_pad_set_activatepull_function (trans->srcpad,
|
gst_pad_set_activatepull_function (trans->srcpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_pull));
|
GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_pull));
|
||||||
gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
|
gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
|
||||||
|
|
||||||
|
trans->passthrough = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
|
@ -187,10 +193,31 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad,
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (trans, "from: %" GST_PTR_FORMAT, caps);
|
GST_DEBUG_OBJECT (trans, "from: %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
if (klass->transform_caps)
|
/* if there is a custom transform function, use this */
|
||||||
ret = klass->transform_caps (trans, pad, caps);
|
if (klass->transform_caps) {
|
||||||
else
|
GstCaps *temp;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
ret = gst_caps_new_empty ();
|
||||||
|
|
||||||
|
/* we send caps with just one structure to the transform
|
||||||
|
* function as this is easier for the element */
|
||||||
|
for (i = 0; i < gst_caps_get_size (caps); i++) {
|
||||||
|
GstCaps *nth;
|
||||||
|
|
||||||
|
nth = gst_caps_copy_nth (caps, i);
|
||||||
|
GST_DEBUG_OBJECT (trans, " from: %" GST_PTR_FORMAT, nth);
|
||||||
|
temp = klass->transform_caps (trans, pad, nth);
|
||||||
|
gst_caps_unref (nth);
|
||||||
|
GST_DEBUG_OBJECT (trans, " to : %" GST_PTR_FORMAT, temp);
|
||||||
|
|
||||||
|
gst_caps_append (ret, temp);
|
||||||
|
}
|
||||||
|
gst_caps_do_simplify (ret);
|
||||||
|
} else {
|
||||||
|
/* else use the identity transform */
|
||||||
ret = gst_caps_ref (caps);
|
ret = gst_caps_ref (caps);
|
||||||
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (trans, "to: %" GST_PTR_FORMAT, ret);
|
GST_DEBUG_OBJECT (trans, "to: %" GST_PTR_FORMAT, ret);
|
||||||
|
|
||||||
|
@ -210,25 +237,66 @@ gst_base_transform_getcaps (GstPad * pad)
|
||||||
|
|
||||||
/* we can do what the peer can */
|
/* we can do what the peer can */
|
||||||
caps = gst_pad_peer_get_caps (otherpad);
|
caps = gst_pad_peer_get_caps (otherpad);
|
||||||
|
|
||||||
if (caps) {
|
if (caps) {
|
||||||
GstCaps *temp;
|
GstCaps *temp;
|
||||||
|
const GstCaps *templ;
|
||||||
|
|
||||||
temp = gst_caps_intersect (caps, gst_pad_get_pad_template_caps (otherpad));
|
GST_DEBUG ("peer caps %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
|
/* filtered against our padtemplate */
|
||||||
|
templ = gst_pad_get_pad_template_caps (otherpad);
|
||||||
|
GST_DEBUG ("our template %" GST_PTR_FORMAT, templ);
|
||||||
|
temp = gst_caps_intersect (caps, templ);
|
||||||
|
GST_DEBUG ("intersected %" GST_PTR_FORMAT, temp);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
|
/* then see what we can tranform this to */
|
||||||
caps = gst_base_transform_transform_caps (trans, otherpad, temp);
|
caps = gst_base_transform_transform_caps (trans, otherpad, temp);
|
||||||
|
GST_DEBUG ("transformed %" GST_PTR_FORMAT, caps);
|
||||||
gst_caps_unref (temp);
|
gst_caps_unref (temp);
|
||||||
temp = gst_caps_intersect (caps, gst_pad_get_pad_template_caps (pad));
|
if (caps == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* and filter against the template again */
|
||||||
|
templ = gst_pad_get_pad_template_caps (pad);
|
||||||
|
GST_DEBUG ("our template %" GST_PTR_FORMAT, templ);
|
||||||
|
temp = gst_caps_intersect (caps, templ);
|
||||||
|
GST_DEBUG ("intersected %" GST_PTR_FORMAT, temp);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
|
/* this is what we can do */
|
||||||
caps = temp;
|
caps = temp;
|
||||||
} else {
|
} else {
|
||||||
/* no peer, our padtemplate is enough then */
|
/* no peer, our padtemplate is enough then */
|
||||||
caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
|
caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
GST_DEBUG ("returning %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_base_transform_configure_caps (GstBaseTransform * trans, GstCaps * in,
|
||||||
|
GstCaps * out)
|
||||||
|
{
|
||||||
|
gboolean ret = TRUE;
|
||||||
|
GstBaseTransformClass *klass;
|
||||||
|
|
||||||
|
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
|
||||||
|
/* no configure the element with the caps */
|
||||||
|
if (klass->set_caps) {
|
||||||
|
ret = klass->set_caps (trans, in, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if all goes well, get the size of the output buffer */
|
||||||
|
if (ret) {
|
||||||
|
trans->out_size = gst_base_transform_get_size (trans);
|
||||||
|
GST_DEBUG ("output buffer size %d", trans->out_size);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
|
@ -252,11 +320,9 @@ gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
/* see how we can transform the input caps */
|
/* see how we can transform the input caps */
|
||||||
othercaps = gst_base_transform_transform_caps (trans, pad, caps);
|
othercaps = gst_base_transform_transform_caps (trans, pad, caps);
|
||||||
|
|
||||||
if (!othercaps || gst_caps_is_empty (othercaps)) {
|
/* check if transform is empty */
|
||||||
GST_DEBUG ("transform returned useless %" GST_PTR_FORMAT, othercaps);
|
if (!othercaps || gst_caps_is_empty (othercaps))
|
||||||
ret = FALSE;
|
goto no_transform;
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gst_caps_is_fixed (othercaps)) {
|
if (!gst_caps_is_fixed (othercaps)) {
|
||||||
GstCaps *temp;
|
GstCaps *temp;
|
||||||
|
@ -266,7 +332,7 @@ gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
temp = gst_caps_intersect (othercaps, caps);
|
temp = gst_caps_intersect (othercaps, caps);
|
||||||
GST_DEBUG ("intersect returned %" GST_PTR_FORMAT, temp);
|
GST_DEBUG ("intersect returned %" GST_PTR_FORMAT, temp);
|
||||||
if (temp) {
|
if (temp) {
|
||||||
if (!gst_caps_is_empty (temp)) {
|
if (!gst_caps_is_empty (temp) && otherpeer) {
|
||||||
GST_DEBUG ("try passthrough with %" GST_PTR_FORMAT, caps);
|
GST_DEBUG ("try passthrough with %" GST_PTR_FORMAT, caps);
|
||||||
/* try passthrough. we know it's fixed, because caps is fixed */
|
/* try passthrough. we know it's fixed, because caps is fixed */
|
||||||
if (gst_pad_accept_caps (otherpeer, caps)) {
|
if (gst_pad_accept_caps (otherpeer, caps)) {
|
||||||
|
@ -312,39 +378,99 @@ gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
GST_DEBUG ("after fixating %" GST_PTR_FORMAT, othercaps);
|
GST_DEBUG ("after fixating %" GST_PTR_FORMAT, othercaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_return_val_if_fail (gst_caps_is_fixed (othercaps), FALSE);
|
/* caps should be fixed now */
|
||||||
|
if (!gst_caps_is_fixed (othercaps))
|
||||||
|
goto could_not_fixate;
|
||||||
|
|
||||||
if (otherpeer && !gst_pad_accept_caps (otherpeer, othercaps)) {
|
/* and peer should accept */
|
||||||
GST_DEBUG ("FAILED to get peer of %" GST_PTR_FORMAT
|
if (otherpeer && !gst_pad_accept_caps (otherpeer, othercaps))
|
||||||
" to accept %" GST_PTR_FORMAT, otherpad, othercaps);
|
goto peer_no_accept;
|
||||||
ret = FALSE;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG ("got final caps %" GST_PTR_FORMAT, othercaps);
|
GST_DEBUG ("got final caps %" GST_PTR_FORMAT, othercaps);
|
||||||
|
|
||||||
/* we know this will work, we implement the setcaps */
|
/* we know this will work, we implement the setcaps */
|
||||||
gst_pad_set_caps (otherpad, othercaps);
|
gst_pad_set_caps (otherpad, othercaps);
|
||||||
|
|
||||||
/* success, let the element know */
|
trans->in_place = gst_caps_is_equal (caps, othercaps);
|
||||||
if (klass->set_caps) {
|
GST_DEBUG ("in_place: %d", trans->in_place);
|
||||||
|
|
||||||
|
/* see if we have to configure the element now */
|
||||||
|
if (!trans->delay_configure) {
|
||||||
if (pad == trans->sinkpad)
|
if (pad == trans->sinkpad)
|
||||||
ret = klass->set_caps (trans, caps, othercaps);
|
ret = gst_base_transform_configure_caps (trans, caps, othercaps);
|
||||||
else
|
else
|
||||||
ret = klass->set_caps (trans, othercaps, caps);
|
ret = gst_base_transform_configure_caps (trans, othercaps, caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
if (otherpeer)
|
if (otherpeer)
|
||||||
gst_object_unref (otherpeer);
|
gst_object_unref (otherpeer);
|
||||||
|
|
||||||
if (othercaps)
|
if (othercaps)
|
||||||
gst_caps_unref (othercaps);
|
gst_caps_unref (othercaps);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_transform:
|
||||||
|
{
|
||||||
|
GST_DEBUG ("transform returned useless %" GST_PTR_FORMAT, othercaps);
|
||||||
|
ret = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
could_not_fixate:
|
||||||
|
{
|
||||||
|
GST_DEBUG ("FAILED to fixate %" GST_PTR_FORMAT, othercaps);
|
||||||
|
ret = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
peer_no_accept:
|
||||||
|
{
|
||||||
|
GST_DEBUG ("FAILED to get peer of %" GST_PTR_FORMAT
|
||||||
|
" to accept %" GST_PTR_FORMAT, otherpad, othercaps);
|
||||||
|
ret = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guint
|
||||||
|
gst_base_transform_get_size (GstBaseTransform * trans)
|
||||||
|
{
|
||||||
|
guint res = -1;
|
||||||
|
GstBaseTransformClass *bclass;
|
||||||
|
|
||||||
|
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
if (bclass->get_size) {
|
||||||
|
res = bclass->get_size (trans);
|
||||||
|
GST_DEBUG ("get size function returned %d", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
|
||||||
|
GstCaps * caps, GstBuffer ** buf)
|
||||||
|
{
|
||||||
|
GstBaseTransform *trans;
|
||||||
|
GstFlowReturn res;
|
||||||
|
|
||||||
|
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
|
if (trans->in_place) {
|
||||||
|
/* we can only proxy the bufferpool if we do in_place transforms */
|
||||||
|
res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);
|
||||||
|
} else {
|
||||||
|
/* else let the default alloc function allocate a buffer */
|
||||||
|
*buf = NULL;
|
||||||
|
res = GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_object_unref (trans);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_base_transform_event (GstPad * pad, GstEvent * event)
|
gst_base_transform_event (GstPad * pad, GstEvent * event)
|
||||||
{
|
{
|
||||||
|
@ -382,6 +508,92 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
|
GstBuffer ** outbuf)
|
||||||
|
{
|
||||||
|
GstBaseTransformClass *bclass;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
|
||||||
|
if (trans->in_place) {
|
||||||
|
if (bclass->transform_ip) {
|
||||||
|
gst_buffer_ref (inbuf);
|
||||||
|
|
||||||
|
/* in place transform and subclass supports method */
|
||||||
|
ret = bclass->transform_ip (trans, inbuf);
|
||||||
|
|
||||||
|
*outbuf = inbuf;
|
||||||
|
} else {
|
||||||
|
/* in place transform and subclass does not support method */
|
||||||
|
if (bclass->transform) {
|
||||||
|
/* make a copy of the buffer */
|
||||||
|
*outbuf = inbuf;
|
||||||
|
inbuf = gst_buffer_copy (inbuf);
|
||||||
|
|
||||||
|
ret = bclass->transform (trans, inbuf, *outbuf);
|
||||||
|
} else {
|
||||||
|
ret = GST_FLOW_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* figure out the output size */
|
||||||
|
if (trans->out_size == -1) {
|
||||||
|
/* ask subclass */
|
||||||
|
if ((trans->out_size = gst_base_transform_get_size (trans)) == -1)
|
||||||
|
/* else we have an error */
|
||||||
|
goto no_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we cannot reconfigure the element yet as we are still processing
|
||||||
|
* the old buffer. We will therefore delay the reconfiguration of the
|
||||||
|
* element until we have processed this last buffer. */
|
||||||
|
trans->delay_configure = TRUE;
|
||||||
|
|
||||||
|
/* no in place transform, get buffer, this might renegotiate. */
|
||||||
|
ret = gst_pad_alloc_buffer (trans->srcpad,
|
||||||
|
GST_BUFFER_OFFSET (inbuf), trans->out_size,
|
||||||
|
GST_PAD_CAPS (trans->srcpad), outbuf);
|
||||||
|
|
||||||
|
trans->delay_configure = FALSE;
|
||||||
|
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
goto no_buffer;
|
||||||
|
|
||||||
|
gst_buffer_stamp (*outbuf, inbuf);
|
||||||
|
|
||||||
|
if (bclass->transform)
|
||||||
|
ret = bclass->transform (trans, inbuf, *outbuf);
|
||||||
|
else
|
||||||
|
ret = GST_FLOW_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
ret =
|
||||||
|
gst_base_transform_configure_caps (trans,
|
||||||
|
GST_PAD_CAPS (trans->sinkpad), GST_PAD_CAPS (trans->srcpad));
|
||||||
|
}
|
||||||
|
gst_buffer_unref (inbuf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_size:
|
||||||
|
{
|
||||||
|
gst_buffer_unref (inbuf);
|
||||||
|
GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
|
||||||
|
("subclass did not specify output size"),
|
||||||
|
("subclass did not specify output size"));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
no_buffer:
|
||||||
|
{
|
||||||
|
gst_buffer_unref (inbuf);
|
||||||
|
GST_DEBUG ("could not get buffer from pool");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_base_transform_getrange (GstPad * pad, guint64 offset,
|
gst_base_transform_getrange (GstPad * pad, guint64 offset,
|
||||||
guint length, GstBuffer ** buffer)
|
guint length, GstBuffer ** buffer)
|
||||||
|
@ -390,16 +602,14 @@ gst_base_transform_getrange (GstPad * pad, guint64 offset,
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
GstBuffer *inbuf;
|
GstBuffer *inbuf;
|
||||||
|
|
||||||
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
|
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
GST_STREAM_LOCK (pad);
|
|
||||||
|
|
||||||
ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf);
|
ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf);
|
||||||
if (ret == GST_FLOW_OK) {
|
if (ret == GST_FLOW_OK) {
|
||||||
ret = gst_base_transform_handle_buffer (trans, inbuf, buffer);
|
ret = gst_base_transform_handle_buffer (trans, inbuf, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_STREAM_UNLOCK (pad);
|
gst_object_unref (trans);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -408,33 +618,17 @@ static GstFlowReturn
|
||||||
gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
|
gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstBaseTransform *trans;
|
GstBaseTransform *trans;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret;
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
|
|
||||||
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
|
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
GST_STREAM_LOCK (pad);
|
|
||||||
|
|
||||||
ret = gst_base_transform_handle_buffer (trans, buffer, &outbuf);
|
ret = gst_base_transform_handle_buffer (trans, buffer, &outbuf);
|
||||||
if (ret == GST_FLOW_OK) {
|
if (ret == GST_FLOW_OK) {
|
||||||
ret = gst_pad_push (trans->srcpad, outbuf);
|
ret = gst_pad_push (trans->srcpad, outbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_STREAM_UNLOCK (pad);
|
gst_object_unref (trans);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
|
|
||||||
GstBuffer ** outbuf)
|
|
||||||
{
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
|
||||||
GstBaseTransformClass *bclass;
|
|
||||||
|
|
||||||
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
|
||||||
if (bclass->transform)
|
|
||||||
ret = bclass->transform (trans, inbuf, outbuf);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -524,6 +718,10 @@ gst_base_transform_change_state (GstElement * element)
|
||||||
case GST_STATE_NULL_TO_READY:
|
case GST_STATE_NULL_TO_READY:
|
||||||
break;
|
break;
|
||||||
case GST_STATE_READY_TO_PAUSED:
|
case GST_STATE_READY_TO_PAUSED:
|
||||||
|
GST_LOCK (trans);
|
||||||
|
trans->in_place = trans->passthrough;
|
||||||
|
trans->out_size = -1;
|
||||||
|
GST_UNLOCK (trans);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_PAUSED_TO_PLAYING:
|
case GST_STATE_PAUSED_TO_PLAYING:
|
||||||
break;
|
break;
|
||||||
|
@ -548,3 +746,48 @@ gst_base_transform_change_state (GstElement * element)
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_base_transform_set_passthrough:
|
||||||
|
* @trans: the #GstBaseTransform to set
|
||||||
|
* @passthrough: boolean indicating passthrough mode.
|
||||||
|
*
|
||||||
|
* Set passthrough mode for this filter by default. This is mostly
|
||||||
|
* usefull for filters that do not care about negotiation.
|
||||||
|
*
|
||||||
|
* MT safe.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_base_transform_set_passthrough (GstBaseTransform * trans,
|
||||||
|
gboolean passthrough)
|
||||||
|
{
|
||||||
|
g_return_if_fail (trans != NULL);
|
||||||
|
|
||||||
|
GST_LOCK (trans);
|
||||||
|
trans->passthrough = passthrough;
|
||||||
|
GST_UNLOCK (trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_base_transform_is_passthrough:
|
||||||
|
* @trans: the #GstBaseTransform to query
|
||||||
|
*
|
||||||
|
* See if @trans is configured as a passthrough transform.
|
||||||
|
*
|
||||||
|
* Returns: TRUE is the transform is configured in passthrough mode.
|
||||||
|
*
|
||||||
|
* MT safe.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_base_transform_is_passthrough (GstBaseTransform * trans)
|
||||||
|
{
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
|
g_return_val_if_fail (trans != NULL, FALSE);
|
||||||
|
|
||||||
|
GST_LOCK (trans);
|
||||||
|
result = trans->passthrough;
|
||||||
|
GST_UNLOCK (trans);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,12 @@ struct _GstBaseTransform {
|
||||||
/* source and sink pads */
|
/* source and sink pads */
|
||||||
GstPad *sinkpad;
|
GstPad *sinkpad;
|
||||||
GstPad *srcpad;
|
GstPad *srcpad;
|
||||||
|
|
||||||
|
gboolean passthrough;
|
||||||
|
|
||||||
|
gboolean in_place;
|
||||||
|
guint out_size;
|
||||||
|
gboolean delay_configure;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstBaseTransformClass {
|
struct _GstBaseTransformClass {
|
||||||
|
@ -65,6 +71,9 @@ struct _GstBaseTransformClass {
|
||||||
gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *incaps,
|
gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *incaps,
|
||||||
GstCaps *outcaps);
|
GstCaps *outcaps);
|
||||||
|
|
||||||
|
/* get the size of the output buffer, -1 on error */
|
||||||
|
guint (*get_size) (GstBaseTransform *trans);
|
||||||
|
|
||||||
/* start and stop processing, ideal for opening/closing the resource */
|
/* start and stop processing, ideal for opening/closing the resource */
|
||||||
gboolean (*start) (GstBaseTransform *trans);
|
gboolean (*start) (GstBaseTransform *trans);
|
||||||
gboolean (*stop) (GstBaseTransform *trans);
|
gboolean (*stop) (GstBaseTransform *trans);
|
||||||
|
@ -73,9 +82,15 @@ struct _GstBaseTransformClass {
|
||||||
|
|
||||||
/* transform one incoming buffer to one outgoing buffer */
|
/* transform one incoming buffer to one outgoing buffer */
|
||||||
GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf,
|
GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf,
|
||||||
GstBuffer **outbuf);
|
GstBuffer *outbuf);
|
||||||
|
|
||||||
|
/* transform a buffer inplace */
|
||||||
|
GstFlowReturn (*transform_ip) (GstBaseTransform *trans, GstBuffer *buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void gst_base_transform_set_passthrough (GstBaseTransform *trans, gboolean passthrough);
|
||||||
|
gboolean gst_base_transform_is_passthrough (GstBaseTransform *trans);
|
||||||
|
|
||||||
GType gst_base_transform_get_type (void);
|
GType gst_base_transform_get_type (void);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -98,7 +98,7 @@ static void gst_identity_get_property (GObject * object, guint prop_id,
|
||||||
|
|
||||||
static gboolean gst_identity_event (GstBaseTransform * trans, GstEvent * event);
|
static gboolean gst_identity_event (GstBaseTransform * trans, GstEvent * event);
|
||||||
static GstFlowReturn gst_identity_transform (GstBaseTransform * trans,
|
static GstFlowReturn gst_identity_transform (GstBaseTransform * trans,
|
||||||
GstBuffer * inbuf, GstBuffer ** outbuf);
|
GstBuffer * inbuf, GstBuffer * outbuf);
|
||||||
static gboolean gst_identity_start (GstBaseTransform * trans);
|
static gboolean gst_identity_start (GstBaseTransform * trans);
|
||||||
static gboolean gst_identity_stop (GstBaseTransform * trans);
|
static gboolean gst_identity_stop (GstBaseTransform * trans);
|
||||||
|
|
||||||
|
@ -190,6 +190,8 @@ gst_identity_class_init (GstIdentityClass * klass)
|
||||||
static void
|
static void
|
||||||
gst_identity_init (GstIdentity * identity)
|
gst_identity_init (GstIdentity * identity)
|
||||||
{
|
{
|
||||||
|
gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (identity), TRUE);
|
||||||
|
|
||||||
identity->sleep_time = DEFAULT_SLEEP_TIME;
|
identity->sleep_time = DEFAULT_SLEEP_TIME;
|
||||||
identity->error_after = DEFAULT_ERROR_AFTER;
|
identity->error_after = DEFAULT_ERROR_AFTER;
|
||||||
identity->drop_probability = DEFAULT_DROP_PROBABILITY;
|
identity->drop_probability = DEFAULT_DROP_PROBABILITY;
|
||||||
|
@ -261,7 +263,7 @@ gst_identity_check_perfect (GstIdentity * identity, GstBuffer * buf)
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
GstBuffer ** outbuf)
|
GstBuffer * outbuf)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstIdentity *identity = GST_IDENTITY (trans);
|
GstIdentity *identity = GST_IDENTITY (trans);
|
||||||
|
@ -274,7 +276,6 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
if (identity->error_after == 0) {
|
if (identity->error_after == 0) {
|
||||||
GST_ELEMENT_ERROR (identity, CORE, FAILED,
|
GST_ELEMENT_ERROR (identity, CORE, FAILED,
|
||||||
(_("Failed after iterations as requested.")), (NULL));
|
(_("Failed after iterations as requested.")), (NULL));
|
||||||
gst_buffer_unref (inbuf);
|
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,7 +295,6 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
GST_BUFFER_FLAGS (inbuf), inbuf);
|
GST_BUFFER_FLAGS (inbuf), inbuf);
|
||||||
GST_UNLOCK (identity);
|
GST_UNLOCK (identity);
|
||||||
g_object_notify (G_OBJECT (identity), "last-message");
|
g_object_notify (G_OBJECT (identity), "last-message");
|
||||||
gst_buffer_unref (inbuf);
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,19 +319,16 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
g_object_notify (G_OBJECT (identity), "last-message");
|
g_object_notify (G_OBJECT (identity), "last-message");
|
||||||
}
|
}
|
||||||
|
|
||||||
*outbuf = gst_buffer_make_writable (inbuf);
|
|
||||||
/* inbuf is no longer usable */
|
|
||||||
|
|
||||||
if (identity->datarate > 0) {
|
if (identity->datarate > 0) {
|
||||||
GstClockTime time = identity->offset * GST_SECOND / identity->datarate;
|
GstClockTime time = identity->offset * GST_SECOND / identity->datarate;
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (*outbuf) = time;
|
GST_BUFFER_TIMESTAMP (outbuf) = time;
|
||||||
GST_BUFFER_DURATION (*outbuf) =
|
GST_BUFFER_DURATION (outbuf) =
|
||||||
GST_BUFFER_SIZE (*outbuf) * GST_SECOND / identity->datarate;
|
GST_BUFFER_SIZE (outbuf) * GST_SECOND / identity->datarate;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
|
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
|
||||||
*outbuf);
|
outbuf);
|
||||||
|
|
||||||
if (identity->sync) {
|
if (identity->sync) {
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
|
@ -344,7 +341,7 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
/* FIXME: actually unlock this somewhere if the state changes */
|
/* FIXME: actually unlock this somewhere if the state changes */
|
||||||
GST_LOCK (identity);
|
GST_LOCK (identity);
|
||||||
identity->clock_id = gst_clock_new_single_shot_id (clock,
|
identity->clock_id = gst_clock_new_single_shot_id (clock,
|
||||||
GST_BUFFER_TIMESTAMP (*outbuf) + GST_ELEMENT (identity)->base_time);
|
GST_BUFFER_TIMESTAMP (outbuf) + GST_ELEMENT (identity)->base_time);
|
||||||
GST_UNLOCK (identity);
|
GST_UNLOCK (identity);
|
||||||
cret = gst_clock_id_wait (identity->clock_id, NULL);
|
cret = gst_clock_id_wait (identity->clock_id, NULL);
|
||||||
GST_LOCK (identity);
|
GST_LOCK (identity);
|
||||||
|
@ -358,7 +355,7 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
identity->offset += GST_BUFFER_SIZE (*outbuf);
|
identity->offset += GST_BUFFER_SIZE (outbuf);
|
||||||
|
|
||||||
if (identity->sleep_time && ret == GST_FLOW_OK)
|
if (identity->sleep_time && ret == GST_FLOW_OK)
|
||||||
g_usleep (identity->sleep_time);
|
g_usleep (identity->sleep_time);
|
||||||
|
|
Loading…
Reference in a new issue