mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 02:01:12 +00:00
tests/network-clock.scm: Commentary update.
Original commit message from CVS: 2005-07-01 Andy Wingo <wingo@pobox.com> * tests/network-clock.scm: Commentary update. * gst/elements/gstidentity.c (PROP_DUPLICATE): Gone daddy gone. Didn't really make sense, not implementable with basetransform, etc. (gst_identity_transform): Unref inbuf via make_writable. Feeble attempt at implementing the sync property, needs an unlock method. * gst/base/gstbasetransform.c (gst_base_transform_transform_caps): New func, by default returns the same caps (the identity transformation). (gst_base_transform_getcaps): Uses transform_caps to return something sensible. (gst_base_transform_setcaps): Complicated logic to get caps on both pads, even if they are different, and to call set_caps once for every time both pads get their caps set. (gst_base_transform_handle_buffer): Give the ref to the transform function. Allows in-place modification of the buffer. * gst/base/gstbasetransform.h (transform_caps): New class method. Given caps on one side, what can I do on the other. (set_caps): Take two caps, one for each side of the element. * gst/gstpad.h: * gst/gstpad.c (gst_pad_fixate_caps): Change prototype to modify caps in place. This is safe because we can check the mutability of the caps, and a good idea because fixate functions are just called as a matter of last resort. (Not actually implemented.) (gst_pad_set_caps): If the caps we're setting is actually the same as the existing pad caps, just update the pointer without calling setcaps. Assert that caps is either NULL or fixed, as per the docs. * gst/gstghostpad.c: Update for fixate changes.
This commit is contained in:
parent
e762446852
commit
c1d34b8acf
18 changed files with 440 additions and 197 deletions
43
ChangeLog
43
ChangeLog
|
@ -1,3 +1,46 @@
|
||||||
|
2005-07-01 Andy Wingo <wingo@pobox.com>
|
||||||
|
|
||||||
|
* tests/network-clock.scm: Commentary update.
|
||||||
|
|
||||||
|
* gst/elements/gstidentity.c (PROP_DUPLICATE): Gone daddy gone.
|
||||||
|
Didn't really make sense, not implementable with basetransform,
|
||||||
|
etc.
|
||||||
|
(gst_identity_transform): Unref inbuf via make_writable. Feeble
|
||||||
|
attempt at implementing the sync property, needs an unlock method.
|
||||||
|
|
||||||
|
* gst/base/gstbasetransform.c (gst_base_transform_transform_caps):
|
||||||
|
New func, by default returns the same caps (the identity
|
||||||
|
transformation).
|
||||||
|
(gst_base_transform_getcaps): Uses transform_caps to return
|
||||||
|
something sensible.
|
||||||
|
(gst_base_transform_setcaps): Complicated logic to get caps on
|
||||||
|
both pads, even if they are different, and to call set_caps once
|
||||||
|
for every time both pads get their caps set.
|
||||||
|
(gst_base_transform_handle_buffer): Give the ref to the transform
|
||||||
|
function. Allows in-place modification of the buffer.
|
||||||
|
|
||||||
|
* gst/base/gstbasetransform.h (transform_caps): New class method.
|
||||||
|
Given caps on one side, what can I do on the other.
|
||||||
|
(set_caps): Take two caps, one for each side of the element.
|
||||||
|
|
||||||
|
* gst/gstpad.h:
|
||||||
|
* gst/gstpad.c (gst_pad_fixate_caps): Change prototype to modify
|
||||||
|
caps in place. This is safe because we can check the mutability of
|
||||||
|
the caps, and a good idea because fixate functions are just called
|
||||||
|
as a matter of last resort. (Not actually implemented.)
|
||||||
|
(gst_pad_set_caps): If the caps we're setting is actually the same
|
||||||
|
as the existing pad caps, just update the pointer without calling
|
||||||
|
setcaps. Assert that caps is either NULL or fixed, as per the
|
||||||
|
docs.
|
||||||
|
|
||||||
|
* gst/gstghostpad.c: Update for fixate changes.
|
||||||
|
|
||||||
|
2005-07-02 Andy Wingo <wingo@pobox.com>
|
||||||
|
|
||||||
|
* gst/gstcaps.c:
|
||||||
|
* gst/gstcaps.h (gst_static_caps_get): Not const return, having
|
||||||
|
two refcounts makes it immutable, which is enough. Doc more.
|
||||||
|
|
||||||
2005-07-02 Jan Schmidt <thaytan@mad.scientist.com>
|
2005-07-02 Jan Schmidt <thaytan@mad.scientist.com>
|
||||||
|
|
||||||
* gst/gstpad.c: (gst_pad_emit_have_data_signal):
|
* gst/gstpad.c: (gst_pad_emit_have_data_signal):
|
||||||
|
|
|
@ -26,6 +26,7 @@ GstBaseTransform
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@parent_class:
|
@parent_class:
|
||||||
|
@transform_caps:
|
||||||
@set_caps:
|
@set_caps:
|
||||||
@start:
|
@start:
|
||||||
@stop:
|
@stop:
|
||||||
|
|
|
@ -90,8 +90,8 @@ Last reviewed on December 13th, 2002 (0.5.0.1)
|
||||||
@queryfunc:
|
@queryfunc:
|
||||||
@intlinkfunc:
|
@intlinkfunc:
|
||||||
@bufferallocfunc:
|
@bufferallocfunc:
|
||||||
@emit_buffer_signals:
|
@do_buffer_signals:
|
||||||
@emit_event_signals:
|
@do_event_signals:
|
||||||
|
|
||||||
<!-- ##### SIGNAL GstPad::have-data ##### -->
|
<!-- ##### SIGNAL GstPad::have-data ##### -->
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -98,7 +98,7 @@ static GstFlowReturn gst_base_transform_chain (GstPad * pad,
|
||||||
GstBuffer * buffer);
|
GstBuffer * buffer);
|
||||||
static GstFlowReturn gst_base_transform_handle_buffer (GstBaseTransform * trans,
|
static GstFlowReturn gst_base_transform_handle_buffer (GstBaseTransform * trans,
|
||||||
GstBuffer * inbuf, GstBuffer ** outbuf);
|
GstBuffer * inbuf, GstBuffer ** outbuf);
|
||||||
static GstCaps *gst_base_transform_proxy_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 guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
|
/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
|
||||||
|
@ -150,7 +150,7 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
||||||
g_return_if_fail (pad_template != NULL);
|
g_return_if_fail (pad_template != NULL);
|
||||||
trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");
|
trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");
|
||||||
gst_pad_set_getcaps_function (trans->sinkpad,
|
gst_pad_set_getcaps_function (trans->sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_proxy_getcaps));
|
GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
|
||||||
gst_pad_set_setcaps_function (trans->sinkpad,
|
gst_pad_set_setcaps_function (trans->sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
|
GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
|
||||||
gst_pad_set_event_function (trans->sinkpad,
|
gst_pad_set_event_function (trans->sinkpad,
|
||||||
|
@ -166,7 +166,9 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
||||||
g_return_if_fail (pad_template != NULL);
|
g_return_if_fail (pad_template != NULL);
|
||||||
trans->srcpad = gst_pad_new_from_template (pad_template, "src");
|
trans->srcpad = gst_pad_new_from_template (pad_template, "src");
|
||||||
gst_pad_set_getcaps_function (trans->srcpad,
|
gst_pad_set_getcaps_function (trans->srcpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_proxy_getcaps));
|
GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
|
||||||
|
gst_pad_set_setcaps_function (trans->srcpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
|
||||||
gst_pad_set_getrange_function (trans->srcpad,
|
gst_pad_set_getrange_function (trans->srcpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_getrange));
|
GST_DEBUG_FUNCPTR (gst_base_transform_getrange));
|
||||||
gst_pad_set_activatepull_function (trans->srcpad,
|
gst_pad_set_activatepull_function (trans->srcpad,
|
||||||
|
@ -175,46 +177,135 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
gst_base_transform_proxy_getcaps (GstPad * pad)
|
gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad,
|
||||||
|
GstCaps * caps)
|
||||||
|
{
|
||||||
|
GstBaseTransformClass *klass;
|
||||||
|
|
||||||
|
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
|
||||||
|
if (klass->transform_caps)
|
||||||
|
return klass->transform_caps (trans, pad, caps);
|
||||||
|
else
|
||||||
|
return gst_caps_ref (caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
gst_base_transform_getcaps (GstPad * pad)
|
||||||
{
|
{
|
||||||
GstPad *otherpad;
|
|
||||||
GstBaseTransform *trans;
|
GstBaseTransform *trans;
|
||||||
|
GstPad *otherpad;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
const GstCaps *templcaps;
|
|
||||||
|
|
||||||
trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
|
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
otherpad = pad == trans->srcpad ? trans->sinkpad : trans->srcpad;
|
otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
|
||||||
|
|
||||||
/* we can do whatever the peer can do */
|
/* we can do what the peer can */
|
||||||
caps = gst_pad_peer_get_caps (otherpad);
|
caps = gst_pad_peer_get_caps (otherpad);
|
||||||
templcaps = gst_pad_get_pad_template_caps (pad);
|
|
||||||
|
|
||||||
if (caps == NULL) {
|
if (caps) {
|
||||||
/* no peer, then the padtemplate is enough */
|
GstCaps *temp;
|
||||||
return gst_caps_copy (templcaps);
|
|
||||||
} else {
|
|
||||||
GstCaps *ret = gst_caps_intersect (caps, templcaps);
|
|
||||||
|
|
||||||
|
temp = gst_base_transform_transform_caps (trans, otherpad, caps);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
return ret;
|
caps = gst_caps_intersect (temp, gst_pad_get_pad_template_caps (pad));
|
||||||
|
gst_caps_unref (temp);
|
||||||
|
} else {
|
||||||
|
/* no peer, our padtemplate is enough then */
|
||||||
|
caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstBaseTransform *trans;
|
GstBaseTransform *trans;
|
||||||
GstBaseTransformClass *bclass;
|
GstBaseTransformClass *klass;
|
||||||
gboolean result = TRUE;
|
GstStructure *structure;
|
||||||
|
GstPad *otherpad, *otherpeer;
|
||||||
|
gboolean ret = TRUE;
|
||||||
|
|
||||||
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
|
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
|
||||||
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
|
||||||
if (bclass->set_caps)
|
otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
|
||||||
result = bclass->set_caps (trans, caps);
|
otherpeer = gst_pad_get_peer (otherpad);
|
||||||
|
|
||||||
return result;
|
if (GST_PAD_IS_IN_SETCAPS (otherpad))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (otherpeer == NULL || gst_pad_accept_caps (otherpeer, caps)) {
|
||||||
|
|
||||||
|
/* the peer accepts the caps as they are */
|
||||||
|
gst_pad_set_caps (otherpad, caps);
|
||||||
|
|
||||||
|
/* let the element know */
|
||||||
|
if (klass->set_caps)
|
||||||
|
klass->set_caps (trans, caps, caps);
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
} else {
|
||||||
|
GstCaps *peercaps;
|
||||||
|
GstCaps *intersect;
|
||||||
|
GstCaps *transform = NULL;
|
||||||
|
GstCaps *othercaps;
|
||||||
|
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
/* other pad has a peer, so we have to figure out how to do the conversion
|
||||||
|
*/
|
||||||
|
/* see how we can transform the input caps */
|
||||||
|
transform = gst_base_transform_transform_caps (trans, pad, caps);
|
||||||
|
|
||||||
|
if (!transform)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* see what the peer can do */
|
||||||
|
peercaps = gst_pad_get_caps (otherpeer);
|
||||||
|
|
||||||
|
GST_DEBUG ("icaps %" GST_PTR_FORMAT, peercaps);
|
||||||
|
GST_DEBUG ("transform %" GST_PTR_FORMAT, transform);
|
||||||
|
|
||||||
|
/* filter against our possibilities */
|
||||||
|
intersect = gst_caps_intersect (peercaps, transform);
|
||||||
|
gst_caps_unref (peercaps);
|
||||||
|
gst_caps_unref (transform);
|
||||||
|
|
||||||
|
GST_DEBUG ("intersect %" GST_PTR_FORMAT, intersect);
|
||||||
|
|
||||||
|
/* take first possibility */
|
||||||
|
othercaps = gst_caps_copy_nth (intersect, 0);
|
||||||
|
gst_caps_unref (intersect);
|
||||||
|
structure = gst_caps_get_structure (othercaps, 0);
|
||||||
|
|
||||||
|
/* and fixate if necessary */
|
||||||
|
gst_pad_fixate_caps (otherpad, othercaps);
|
||||||
|
|
||||||
|
g_return_val_if_fail (gst_caps_is_fixed (othercaps), FALSE);
|
||||||
|
|
||||||
|
gst_pad_set_caps (otherpad, othercaps);
|
||||||
|
|
||||||
|
/* let the element know */
|
||||||
|
if (klass->set_caps) {
|
||||||
|
if (pad == trans->sinkpad) {
|
||||||
|
klass->set_caps (trans, caps, othercaps);
|
||||||
|
} else {
|
||||||
|
klass->set_caps (trans, othercaps, caps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
if (otherpeer)
|
||||||
|
gst_object_unref (otherpeer);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -308,8 +399,6 @@ gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
if (bclass->transform)
|
if (bclass->transform)
|
||||||
ret = bclass->transform (trans, inbuf, outbuf);
|
ret = bclass->transform (trans, inbuf, outbuf);
|
||||||
|
|
||||||
gst_buffer_unref (inbuf);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,9 +57,13 @@ struct _GstBaseTransformClass {
|
||||||
/*< public >*/
|
/*< public >*/
|
||||||
/* virtual methods for subclasses */
|
/* virtual methods for subclasses */
|
||||||
|
|
||||||
|
/* given caps on one pad, what can I do on the other pad */
|
||||||
|
GstCaps* (*transform_caps) (GstBaseTransform *trans, GstPad *pad,
|
||||||
|
GstCaps *caps);
|
||||||
|
|
||||||
/* notify the subclass of new caps */
|
/* notify the subclass of new caps */
|
||||||
gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *caps);
|
gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *incaps,
|
||||||
|
GstCaps *outcaps);
|
||||||
|
|
||||||
/* 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);
|
||||||
|
@ -68,7 +72,8 @@ struct _GstBaseTransformClass {
|
||||||
gboolean (*event) (GstBaseTransform *trans, GstEvent *event);
|
gboolean (*event) (GstBaseTransform *trans, GstEvent *event);
|
||||||
|
|
||||||
/* transform one incoming buffer to one outgoing buffer */
|
/* transform one incoming buffer to one outgoing buffer */
|
||||||
GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer **outbuf);
|
GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf,
|
||||||
|
GstBuffer **outbuf);
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_base_transform_get_type (void);
|
GType gst_base_transform_get_type (void);
|
||||||
|
|
|
@ -73,7 +73,6 @@ enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_SLEEP_TIME,
|
PROP_SLEEP_TIME,
|
||||||
PROP_DUPLICATE,
|
|
||||||
PROP_ERROR_AFTER,
|
PROP_ERROR_AFTER,
|
||||||
PROP_DROP_PROBABILITY,
|
PROP_DROP_PROBABILITY,
|
||||||
PROP_DATARATE,
|
PROP_DATARATE,
|
||||||
|
@ -147,10 +146,6 @@ gst_identity_class_init (GstIdentityClass * klass)
|
||||||
g_param_spec_uint ("sleep-time", "Sleep time",
|
g_param_spec_uint ("sleep-time", "Sleep time",
|
||||||
"Microseconds to sleep between processing", 0, G_MAXUINT,
|
"Microseconds to sleep between processing", 0, G_MAXUINT,
|
||||||
DEFAULT_SLEEP_TIME, G_PARAM_READWRITE));
|
DEFAULT_SLEEP_TIME, G_PARAM_READWRITE));
|
||||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DUPLICATE,
|
|
||||||
g_param_spec_uint ("duplicate", "Duplicate Buffers",
|
|
||||||
"Push the buffers N times", 0, G_MAXUINT, DEFAULT_DUPLICATE,
|
|
||||||
G_PARAM_READWRITE));
|
|
||||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ERROR_AFTER,
|
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ERROR_AFTER,
|
||||||
g_param_spec_int ("error_after", "Error After", "Error after N buffers",
|
g_param_spec_int ("error_after", "Error After", "Error after N buffers",
|
||||||
G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER, G_PARAM_READWRITE));
|
G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER, G_PARAM_READWRITE));
|
||||||
|
@ -196,7 +191,6 @@ static void
|
||||||
gst_identity_init (GstIdentity * identity)
|
gst_identity_init (GstIdentity * identity)
|
||||||
{
|
{
|
||||||
identity->sleep_time = DEFAULT_SLEEP_TIME;
|
identity->sleep_time = DEFAULT_SLEEP_TIME;
|
||||||
identity->duplicate = DEFAULT_DUPLICATE;
|
|
||||||
identity->error_after = DEFAULT_ERROR_AFTER;
|
identity->error_after = DEFAULT_ERROR_AFTER;
|
||||||
identity->drop_probability = DEFAULT_DROP_PROBABILITY;
|
identity->drop_probability = DEFAULT_DROP_PROBABILITY;
|
||||||
identity->datarate = DEFAULT_DATARATE;
|
identity->datarate = DEFAULT_DATARATE;
|
||||||
|
@ -271,7 +265,6 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstIdentity *identity = GST_IDENTITY (trans);
|
GstIdentity *identity = GST_IDENTITY (trans);
|
||||||
guint i;
|
|
||||||
|
|
||||||
if (identity->check_perfect)
|
if (identity->check_perfect)
|
||||||
gst_identity_check_perfect (identity, inbuf);
|
gst_identity_check_perfect (identity, inbuf);
|
||||||
|
@ -281,6 +274,7 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,6 +294,7 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,56 +303,66 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
gst_util_dump_mem (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
|
gst_util_dump_mem (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = identity->duplicate; i; i--) {
|
if (!identity->silent) {
|
||||||
GstClockTime time;
|
GST_LOCK (identity);
|
||||||
|
g_free (identity->last_message);
|
||||||
if (!identity->silent) {
|
identity->last_message =
|
||||||
GST_LOCK (identity);
|
g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, timestamp: %"
|
||||||
g_free (identity->last_message);
|
GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
|
||||||
identity->last_message =
|
G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p",
|
||||||
g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, timestamp: %"
|
GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (inbuf),
|
||||||
GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
|
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
|
||||||
G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p",
|
GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)),
|
||||||
GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (inbuf),
|
GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf),
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
|
GST_BUFFER_FLAGS (inbuf), inbuf);
|
||||||
GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)),
|
GST_UNLOCK (identity);
|
||||||
GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf),
|
g_object_notify (G_OBJECT (identity), "last-message");
|
||||||
GST_BUFFER_FLAGS (inbuf), inbuf);
|
|
||||||
GST_UNLOCK (identity);
|
|
||||||
g_object_notify (G_OBJECT (identity), "last-message");
|
|
||||||
}
|
|
||||||
|
|
||||||
time = GST_BUFFER_TIMESTAMP (inbuf);
|
|
||||||
|
|
||||||
if (identity->datarate > 0) {
|
|
||||||
time = identity->offset * GST_SECOND / identity->datarate;
|
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (inbuf) = time;
|
|
||||||
GST_BUFFER_DURATION (inbuf) =
|
|
||||||
GST_BUFFER_SIZE (inbuf) * GST_SECOND / identity->datarate;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
|
|
||||||
inbuf);
|
|
||||||
|
|
||||||
if (i > 1)
|
|
||||||
gst_buffer_ref (inbuf);
|
|
||||||
|
|
||||||
if (identity->sync) {
|
|
||||||
if (GST_ELEMENT (identity)->clock) {
|
|
||||||
/* gst_element_wait (GST_ELEMENT (identity), time); */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
identity->offset += GST_BUFFER_SIZE (inbuf);
|
|
||||||
|
|
||||||
if (identity->sleep_time)
|
|
||||||
g_usleep (identity->sleep_time);
|
|
||||||
|
|
||||||
gst_buffer_ref (inbuf);
|
|
||||||
*outbuf = inbuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*outbuf = gst_buffer_make_writable (inbuf);
|
||||||
|
/* inbuf is no longer usable */
|
||||||
|
|
||||||
|
if (identity->datarate > 0) {
|
||||||
|
GstClockTime time = identity->offset * GST_SECOND / identity->datarate;
|
||||||
|
|
||||||
|
GST_BUFFER_TIMESTAMP (*outbuf) = time;
|
||||||
|
GST_BUFFER_DURATION (*outbuf) =
|
||||||
|
GST_BUFFER_SIZE (*outbuf) * GST_SECOND / identity->datarate;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
|
||||||
|
*outbuf);
|
||||||
|
|
||||||
|
if (identity->sync) {
|
||||||
|
GstClock *clock;
|
||||||
|
GstClockReturn cret;
|
||||||
|
|
||||||
|
clock = GST_ELEMENT (identity)->clock;
|
||||||
|
|
||||||
|
if (clock) {
|
||||||
|
/* save id if we need to unlock */
|
||||||
|
/* FIXME: actually unlock this somewhere if the state changes */
|
||||||
|
GST_LOCK (identity);
|
||||||
|
identity->clock_id = gst_clock_new_single_shot_id (clock,
|
||||||
|
GST_BUFFER_TIMESTAMP (*outbuf) + GST_ELEMENT (identity)->base_time);
|
||||||
|
GST_UNLOCK (identity);
|
||||||
|
cret = gst_clock_id_wait (identity->clock_id, NULL);
|
||||||
|
GST_LOCK (identity);
|
||||||
|
if (identity->clock_id) {
|
||||||
|
gst_clock_id_unref (identity->clock_id);
|
||||||
|
identity->clock_id = NULL;
|
||||||
|
}
|
||||||
|
GST_UNLOCK (identity);
|
||||||
|
if (cret == GST_CLOCK_UNSCHEDULED)
|
||||||
|
ret = GST_FLOW_UNEXPECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
identity->offset += GST_BUFFER_SIZE (*outbuf);
|
||||||
|
|
||||||
|
if (identity->sleep_time && ret == GST_FLOW_OK)
|
||||||
|
g_usleep (identity->sleep_time);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,9 +381,6 @@ gst_identity_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_SILENT:
|
case PROP_SILENT:
|
||||||
identity->silent = g_value_get_boolean (value);
|
identity->silent = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
case PROP_DUPLICATE:
|
|
||||||
identity->duplicate = g_value_get_uint (value);
|
|
||||||
break;
|
|
||||||
case PROP_DUMP:
|
case PROP_DUMP:
|
||||||
identity->dump = g_value_get_boolean (value);
|
identity->dump = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
@ -415,9 +417,6 @@ gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_SLEEP_TIME:
|
case PROP_SLEEP_TIME:
|
||||||
g_value_set_uint (value, identity->sleep_time);
|
g_value_set_uint (value, identity->sleep_time);
|
||||||
break;
|
break;
|
||||||
case PROP_DUPLICATE:
|
|
||||||
g_value_set_uint (value, identity->duplicate);
|
|
||||||
break;
|
|
||||||
case PROP_ERROR_AFTER:
|
case PROP_ERROR_AFTER:
|
||||||
g_value_set_int (value, identity->error_after);
|
g_value_set_int (value, identity->error_after);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -48,7 +48,7 @@ typedef struct _GstIdentityClass GstIdentityClass;
|
||||||
struct _GstIdentity {
|
struct _GstIdentity {
|
||||||
GstBaseTransform element;
|
GstBaseTransform element;
|
||||||
|
|
||||||
guint duplicate;
|
GstClockID clock_id;
|
||||||
gint error_after;
|
gint error_after;
|
||||||
gfloat drop_probability;
|
gfloat drop_probability;
|
||||||
gint datarate;
|
gint datarate;
|
||||||
|
|
|
@ -347,9 +347,11 @@ gst_caps_unref (GstCaps * caps)
|
||||||
*
|
*
|
||||||
* Converts a #GstStaticCaps to a #GstCaps.
|
* Converts a #GstStaticCaps to a #GstCaps.
|
||||||
*
|
*
|
||||||
* Returns: the new #GstCaps
|
* Returns: A pointer to the #GstCaps. Although you do not have a reference on
|
||||||
|
* the caps, the core will never drop its references. (The core has two
|
||||||
|
* references on the caps so it will be immutable.)
|
||||||
*/
|
*/
|
||||||
const GstCaps *
|
GstCaps *
|
||||||
gst_static_caps_get (GstStaticCaps * static_caps)
|
gst_static_caps_get (GstStaticCaps * static_caps)
|
||||||
{
|
{
|
||||||
GstCaps *caps = (GstCaps *) static_caps;
|
GstCaps *caps = (GstCaps *) static_caps;
|
||||||
|
|
|
@ -98,7 +98,7 @@ GstCaps * gst_caps_copy (const GstCaps * caps);
|
||||||
GstCaps * gst_caps_make_writable (GstCaps *caps);
|
GstCaps * gst_caps_make_writable (GstCaps *caps);
|
||||||
void gst_caps_unref (GstCaps* caps);
|
void gst_caps_unref (GstCaps* caps);
|
||||||
|
|
||||||
G_CONST_RETURN GstCaps * gst_static_caps_get (GstStaticCaps *static_caps);
|
GstCaps * gst_static_caps_get (GstStaticCaps *static_caps);
|
||||||
|
|
||||||
/* manipulation */
|
/* manipulation */
|
||||||
void gst_caps_append (GstCaps *caps1,
|
void gst_caps_append (GstCaps *caps1,
|
||||||
|
|
|
@ -279,14 +279,14 @@ gst_proxy_pad_do_acceptcaps (GstPad * pad, GstCaps * caps)
|
||||||
return gst_pad_accept_caps (target, caps);
|
return gst_pad_accept_caps (target, caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static void
|
||||||
gst_proxy_pad_do_fixatecaps (GstPad * pad, GstCaps * caps)
|
gst_proxy_pad_do_fixatecaps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstPad *target = GST_PROXY_PAD_TARGET (pad);
|
GstPad *target = GST_PROXY_PAD_TARGET (pad);
|
||||||
|
|
||||||
g_return_val_if_fail (target != NULL, NULL);
|
g_return_if_fail (target != NULL);
|
||||||
|
|
||||||
return gst_pad_fixate_caps (target, caps);
|
gst_pad_fixate_caps (target, caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
25
gst/gstpad.c
25
gst/gstpad.c
|
@ -1748,15 +1748,13 @@ was_dispatching:
|
||||||
* gst_pad_fixate_caps:
|
* gst_pad_fixate_caps:
|
||||||
* @pad: a #GstPad to fixate
|
* @pad: a #GstPad to fixate
|
||||||
*
|
*
|
||||||
* Fixate a caps on the given pad.
|
* Fixate a caps on the given pad. Modifies the caps in place, so you should be
|
||||||
*
|
* that the caps are actually writable (see gst_caps_make_writable()).
|
||||||
* Returns: a fixated #GstCaps.
|
|
||||||
*/
|
*/
|
||||||
GstCaps *
|
void
|
||||||
gst_pad_fixate_caps (GstPad * pad, GstCaps * caps)
|
gst_pad_fixate_caps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
/* FIXME, implement me, call the fixate function for the pad */
|
/* FIXME, implement me, call the fixate function for the pad */
|
||||||
return caps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1857,12 +1855,20 @@ gboolean
|
||||||
gst_pad_set_caps (GstPad * pad, GstCaps * caps)
|
gst_pad_set_caps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstPadSetCapsFunction setcaps;
|
GstPadSetCapsFunction setcaps;
|
||||||
|
GstCaps *existing;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||||
|
g_return_val_if_fail (caps == NULL || gst_caps_is_fixed (caps), FALSE);
|
||||||
|
|
||||||
GST_LOCK (pad);
|
GST_LOCK (pad);
|
||||||
setcaps = GST_PAD_SETCAPSFUNC (pad);
|
setcaps = GST_PAD_SETCAPSFUNC (pad);
|
||||||
|
|
||||||
|
existing = GST_PAD_CAPS (pad);
|
||||||
|
if (caps == existing)
|
||||||
|
goto setting_same_caps;
|
||||||
|
else if (caps && existing && gst_caps_is_equal (caps, existing))
|
||||||
|
goto setting_same_caps;
|
||||||
|
|
||||||
/* call setcaps function to configure the pad */
|
/* call setcaps function to configure the pad */
|
||||||
if (setcaps != NULL && caps) {
|
if (setcaps != NULL && caps) {
|
||||||
if (!GST_PAD_IS_IN_SETCAPS (pad)) {
|
if (!GST_PAD_IS_IN_SETCAPS (pad)) {
|
||||||
|
@ -1887,6 +1893,15 @@ gst_pad_set_caps (GstPad * pad, GstCaps * caps)
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
setting_same_caps:
|
||||||
|
{
|
||||||
|
GST_UNLOCK (pad);
|
||||||
|
gst_caps_replace (&GST_PAD_CAPS (pad), caps);
|
||||||
|
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
|
||||||
|
"caps %" GST_PTR_FORMAT " same as existing, updating ptr only", caps);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
/* errors */
|
||||||
could_not_set:
|
could_not_set:
|
||||||
{
|
{
|
||||||
GST_LOCK (pad);
|
GST_LOCK (pad);
|
||||||
|
|
|
@ -117,7 +117,7 @@ typedef void (*GstPadUnlinkFunction) (GstPad *pad);
|
||||||
typedef GstCaps* (*GstPadGetCapsFunction) (GstPad *pad);
|
typedef GstCaps* (*GstPadGetCapsFunction) (GstPad *pad);
|
||||||
typedef gboolean (*GstPadSetCapsFunction) (GstPad *pad, GstCaps *caps);
|
typedef gboolean (*GstPadSetCapsFunction) (GstPad *pad, GstCaps *caps);
|
||||||
typedef gboolean (*GstPadAcceptCapsFunction) (GstPad *pad, GstCaps *caps);
|
typedef gboolean (*GstPadAcceptCapsFunction) (GstPad *pad, GstCaps *caps);
|
||||||
typedef GstCaps* (*GstPadFixateCapsFunction) (GstPad *pad, GstCaps *caps);
|
typedef void (*GstPadFixateCapsFunction) (GstPad *pad, GstCaps *caps);
|
||||||
typedef GstFlowReturn (*GstPadBufferAllocFunction) (GstPad *pad, guint64 offset, guint size,
|
typedef GstFlowReturn (*GstPadBufferAllocFunction) (GstPad *pad, guint64 offset, guint size,
|
||||||
GstCaps *caps, GstBuffer **buf);
|
GstCaps *caps, GstBuffer **buf);
|
||||||
/* misc */
|
/* misc */
|
||||||
|
@ -414,7 +414,7 @@ G_CONST_RETURN GstCaps* gst_pad_get_pad_template_caps (GstPad *pad);
|
||||||
|
|
||||||
/* capsnego function for connected/unconnected pads */
|
/* capsnego function for connected/unconnected pads */
|
||||||
GstCaps * gst_pad_get_caps (GstPad * pad);
|
GstCaps * gst_pad_get_caps (GstPad * pad);
|
||||||
GstCaps* gst_pad_fixate_caps (GstPad * pad, GstCaps *caps);
|
void gst_pad_fixate_caps (GstPad * pad, GstCaps *caps);
|
||||||
gboolean gst_pad_accept_caps (GstPad * pad, GstCaps *caps);
|
gboolean gst_pad_accept_caps (GstPad * pad, GstCaps *caps);
|
||||||
gboolean gst_pad_set_caps (GstPad * pad, GstCaps *caps);
|
gboolean gst_pad_set_caps (GstPad * pad, GstCaps *caps);
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ static GstFlowReturn gst_base_transform_chain (GstPad * pad,
|
||||||
GstBuffer * buffer);
|
GstBuffer * buffer);
|
||||||
static GstFlowReturn gst_base_transform_handle_buffer (GstBaseTransform * trans,
|
static GstFlowReturn gst_base_transform_handle_buffer (GstBaseTransform * trans,
|
||||||
GstBuffer * inbuf, GstBuffer ** outbuf);
|
GstBuffer * inbuf, GstBuffer ** outbuf);
|
||||||
static GstCaps *gst_base_transform_proxy_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 guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
|
/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
|
||||||
|
@ -150,7 +150,7 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
||||||
g_return_if_fail (pad_template != NULL);
|
g_return_if_fail (pad_template != NULL);
|
||||||
trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");
|
trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");
|
||||||
gst_pad_set_getcaps_function (trans->sinkpad,
|
gst_pad_set_getcaps_function (trans->sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_proxy_getcaps));
|
GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
|
||||||
gst_pad_set_setcaps_function (trans->sinkpad,
|
gst_pad_set_setcaps_function (trans->sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
|
GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
|
||||||
gst_pad_set_event_function (trans->sinkpad,
|
gst_pad_set_event_function (trans->sinkpad,
|
||||||
|
@ -166,7 +166,9 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
||||||
g_return_if_fail (pad_template != NULL);
|
g_return_if_fail (pad_template != NULL);
|
||||||
trans->srcpad = gst_pad_new_from_template (pad_template, "src");
|
trans->srcpad = gst_pad_new_from_template (pad_template, "src");
|
||||||
gst_pad_set_getcaps_function (trans->srcpad,
|
gst_pad_set_getcaps_function (trans->srcpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_proxy_getcaps));
|
GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
|
||||||
|
gst_pad_set_setcaps_function (trans->srcpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
|
||||||
gst_pad_set_getrange_function (trans->srcpad,
|
gst_pad_set_getrange_function (trans->srcpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_transform_getrange));
|
GST_DEBUG_FUNCPTR (gst_base_transform_getrange));
|
||||||
gst_pad_set_activatepull_function (trans->srcpad,
|
gst_pad_set_activatepull_function (trans->srcpad,
|
||||||
|
@ -175,46 +177,135 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
gst_base_transform_proxy_getcaps (GstPad * pad)
|
gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad,
|
||||||
|
GstCaps * caps)
|
||||||
|
{
|
||||||
|
GstBaseTransformClass *klass;
|
||||||
|
|
||||||
|
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
|
||||||
|
if (klass->transform_caps)
|
||||||
|
return klass->transform_caps (trans, pad, caps);
|
||||||
|
else
|
||||||
|
return gst_caps_ref (caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
gst_base_transform_getcaps (GstPad * pad)
|
||||||
{
|
{
|
||||||
GstPad *otherpad;
|
|
||||||
GstBaseTransform *trans;
|
GstBaseTransform *trans;
|
||||||
|
GstPad *otherpad;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
const GstCaps *templcaps;
|
|
||||||
|
|
||||||
trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
|
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
otherpad = pad == trans->srcpad ? trans->sinkpad : trans->srcpad;
|
otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
|
||||||
|
|
||||||
/* we can do whatever the peer can do */
|
/* we can do what the peer can */
|
||||||
caps = gst_pad_peer_get_caps (otherpad);
|
caps = gst_pad_peer_get_caps (otherpad);
|
||||||
templcaps = gst_pad_get_pad_template_caps (pad);
|
|
||||||
|
|
||||||
if (caps == NULL) {
|
if (caps) {
|
||||||
/* no peer, then the padtemplate is enough */
|
GstCaps *temp;
|
||||||
return gst_caps_copy (templcaps);
|
|
||||||
} else {
|
|
||||||
GstCaps *ret = gst_caps_intersect (caps, templcaps);
|
|
||||||
|
|
||||||
|
temp = gst_base_transform_transform_caps (trans, otherpad, caps);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
return ret;
|
caps = gst_caps_intersect (temp, gst_pad_get_pad_template_caps (pad));
|
||||||
|
gst_caps_unref (temp);
|
||||||
|
} else {
|
||||||
|
/* no peer, our padtemplate is enough then */
|
||||||
|
caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstBaseTransform *trans;
|
GstBaseTransform *trans;
|
||||||
GstBaseTransformClass *bclass;
|
GstBaseTransformClass *klass;
|
||||||
gboolean result = TRUE;
|
GstStructure *structure;
|
||||||
|
GstPad *otherpad, *otherpeer;
|
||||||
|
gboolean ret = TRUE;
|
||||||
|
|
||||||
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
|
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
|
||||||
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||||
|
|
||||||
if (bclass->set_caps)
|
otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
|
||||||
result = bclass->set_caps (trans, caps);
|
otherpeer = gst_pad_get_peer (otherpad);
|
||||||
|
|
||||||
return result;
|
if (GST_PAD_IS_IN_SETCAPS (otherpad))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (otherpeer == NULL || gst_pad_accept_caps (otherpeer, caps)) {
|
||||||
|
|
||||||
|
/* the peer accepts the caps as they are */
|
||||||
|
gst_pad_set_caps (otherpad, caps);
|
||||||
|
|
||||||
|
/* let the element know */
|
||||||
|
if (klass->set_caps)
|
||||||
|
klass->set_caps (trans, caps, caps);
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
} else {
|
||||||
|
GstCaps *peercaps;
|
||||||
|
GstCaps *intersect;
|
||||||
|
GstCaps *transform = NULL;
|
||||||
|
GstCaps *othercaps;
|
||||||
|
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
/* other pad has a peer, so we have to figure out how to do the conversion
|
||||||
|
*/
|
||||||
|
/* see how we can transform the input caps */
|
||||||
|
transform = gst_base_transform_transform_caps (trans, pad, caps);
|
||||||
|
|
||||||
|
if (!transform)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* see what the peer can do */
|
||||||
|
peercaps = gst_pad_get_caps (otherpeer);
|
||||||
|
|
||||||
|
GST_DEBUG ("icaps %" GST_PTR_FORMAT, peercaps);
|
||||||
|
GST_DEBUG ("transform %" GST_PTR_FORMAT, transform);
|
||||||
|
|
||||||
|
/* filter against our possibilities */
|
||||||
|
intersect = gst_caps_intersect (peercaps, transform);
|
||||||
|
gst_caps_unref (peercaps);
|
||||||
|
gst_caps_unref (transform);
|
||||||
|
|
||||||
|
GST_DEBUG ("intersect %" GST_PTR_FORMAT, intersect);
|
||||||
|
|
||||||
|
/* take first possibility */
|
||||||
|
othercaps = gst_caps_copy_nth (intersect, 0);
|
||||||
|
gst_caps_unref (intersect);
|
||||||
|
structure = gst_caps_get_structure (othercaps, 0);
|
||||||
|
|
||||||
|
/* and fixate if necessary */
|
||||||
|
gst_pad_fixate_caps (otherpad, othercaps);
|
||||||
|
|
||||||
|
g_return_val_if_fail (gst_caps_is_fixed (othercaps), FALSE);
|
||||||
|
|
||||||
|
gst_pad_set_caps (otherpad, othercaps);
|
||||||
|
|
||||||
|
/* let the element know */
|
||||||
|
if (klass->set_caps) {
|
||||||
|
if (pad == trans->sinkpad) {
|
||||||
|
klass->set_caps (trans, caps, othercaps);
|
||||||
|
} else {
|
||||||
|
klass->set_caps (trans, othercaps, caps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
if (otherpeer)
|
||||||
|
gst_object_unref (otherpeer);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -308,8 +399,6 @@ gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
if (bclass->transform)
|
if (bclass->transform)
|
||||||
ret = bclass->transform (trans, inbuf, outbuf);
|
ret = bclass->transform (trans, inbuf, outbuf);
|
||||||
|
|
||||||
gst_buffer_unref (inbuf);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,9 +57,13 @@ struct _GstBaseTransformClass {
|
||||||
/*< public >*/
|
/*< public >*/
|
||||||
/* virtual methods for subclasses */
|
/* virtual methods for subclasses */
|
||||||
|
|
||||||
|
/* given caps on one pad, what can I do on the other pad */
|
||||||
|
GstCaps* (*transform_caps) (GstBaseTransform *trans, GstPad *pad,
|
||||||
|
GstCaps *caps);
|
||||||
|
|
||||||
/* notify the subclass of new caps */
|
/* notify the subclass of new caps */
|
||||||
gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *caps);
|
gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *incaps,
|
||||||
|
GstCaps *outcaps);
|
||||||
|
|
||||||
/* 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);
|
||||||
|
@ -68,7 +72,8 @@ struct _GstBaseTransformClass {
|
||||||
gboolean (*event) (GstBaseTransform *trans, GstEvent *event);
|
gboolean (*event) (GstBaseTransform *trans, GstEvent *event);
|
||||||
|
|
||||||
/* transform one incoming buffer to one outgoing buffer */
|
/* transform one incoming buffer to one outgoing buffer */
|
||||||
GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer **outbuf);
|
GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf,
|
||||||
|
GstBuffer **outbuf);
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_base_transform_get_type (void);
|
GType gst_base_transform_get_type (void);
|
||||||
|
|
|
@ -73,7 +73,6 @@ enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_SLEEP_TIME,
|
PROP_SLEEP_TIME,
|
||||||
PROP_DUPLICATE,
|
|
||||||
PROP_ERROR_AFTER,
|
PROP_ERROR_AFTER,
|
||||||
PROP_DROP_PROBABILITY,
|
PROP_DROP_PROBABILITY,
|
||||||
PROP_DATARATE,
|
PROP_DATARATE,
|
||||||
|
@ -147,10 +146,6 @@ gst_identity_class_init (GstIdentityClass * klass)
|
||||||
g_param_spec_uint ("sleep-time", "Sleep time",
|
g_param_spec_uint ("sleep-time", "Sleep time",
|
||||||
"Microseconds to sleep between processing", 0, G_MAXUINT,
|
"Microseconds to sleep between processing", 0, G_MAXUINT,
|
||||||
DEFAULT_SLEEP_TIME, G_PARAM_READWRITE));
|
DEFAULT_SLEEP_TIME, G_PARAM_READWRITE));
|
||||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DUPLICATE,
|
|
||||||
g_param_spec_uint ("duplicate", "Duplicate Buffers",
|
|
||||||
"Push the buffers N times", 0, G_MAXUINT, DEFAULT_DUPLICATE,
|
|
||||||
G_PARAM_READWRITE));
|
|
||||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ERROR_AFTER,
|
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ERROR_AFTER,
|
||||||
g_param_spec_int ("error_after", "Error After", "Error after N buffers",
|
g_param_spec_int ("error_after", "Error After", "Error after N buffers",
|
||||||
G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER, G_PARAM_READWRITE));
|
G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER, G_PARAM_READWRITE));
|
||||||
|
@ -196,7 +191,6 @@ static void
|
||||||
gst_identity_init (GstIdentity * identity)
|
gst_identity_init (GstIdentity * identity)
|
||||||
{
|
{
|
||||||
identity->sleep_time = DEFAULT_SLEEP_TIME;
|
identity->sleep_time = DEFAULT_SLEEP_TIME;
|
||||||
identity->duplicate = DEFAULT_DUPLICATE;
|
|
||||||
identity->error_after = DEFAULT_ERROR_AFTER;
|
identity->error_after = DEFAULT_ERROR_AFTER;
|
||||||
identity->drop_probability = DEFAULT_DROP_PROBABILITY;
|
identity->drop_probability = DEFAULT_DROP_PROBABILITY;
|
||||||
identity->datarate = DEFAULT_DATARATE;
|
identity->datarate = DEFAULT_DATARATE;
|
||||||
|
@ -271,7 +265,6 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstIdentity *identity = GST_IDENTITY (trans);
|
GstIdentity *identity = GST_IDENTITY (trans);
|
||||||
guint i;
|
|
||||||
|
|
||||||
if (identity->check_perfect)
|
if (identity->check_perfect)
|
||||||
gst_identity_check_perfect (identity, inbuf);
|
gst_identity_check_perfect (identity, inbuf);
|
||||||
|
@ -281,6 +274,7 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,6 +294,7 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,56 +303,66 @@ gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
gst_util_dump_mem (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
|
gst_util_dump_mem (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = identity->duplicate; i; i--) {
|
if (!identity->silent) {
|
||||||
GstClockTime time;
|
GST_LOCK (identity);
|
||||||
|
g_free (identity->last_message);
|
||||||
if (!identity->silent) {
|
identity->last_message =
|
||||||
GST_LOCK (identity);
|
g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, timestamp: %"
|
||||||
g_free (identity->last_message);
|
GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
|
||||||
identity->last_message =
|
G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p",
|
||||||
g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, timestamp: %"
|
GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (inbuf),
|
||||||
GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
|
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
|
||||||
G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p",
|
GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)),
|
||||||
GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (inbuf),
|
GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf),
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
|
GST_BUFFER_FLAGS (inbuf), inbuf);
|
||||||
GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)),
|
GST_UNLOCK (identity);
|
||||||
GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf),
|
g_object_notify (G_OBJECT (identity), "last-message");
|
||||||
GST_BUFFER_FLAGS (inbuf), inbuf);
|
|
||||||
GST_UNLOCK (identity);
|
|
||||||
g_object_notify (G_OBJECT (identity), "last-message");
|
|
||||||
}
|
|
||||||
|
|
||||||
time = GST_BUFFER_TIMESTAMP (inbuf);
|
|
||||||
|
|
||||||
if (identity->datarate > 0) {
|
|
||||||
time = identity->offset * GST_SECOND / identity->datarate;
|
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (inbuf) = time;
|
|
||||||
GST_BUFFER_DURATION (inbuf) =
|
|
||||||
GST_BUFFER_SIZE (inbuf) * GST_SECOND / identity->datarate;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
|
|
||||||
inbuf);
|
|
||||||
|
|
||||||
if (i > 1)
|
|
||||||
gst_buffer_ref (inbuf);
|
|
||||||
|
|
||||||
if (identity->sync) {
|
|
||||||
if (GST_ELEMENT (identity)->clock) {
|
|
||||||
/* gst_element_wait (GST_ELEMENT (identity), time); */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
identity->offset += GST_BUFFER_SIZE (inbuf);
|
|
||||||
|
|
||||||
if (identity->sleep_time)
|
|
||||||
g_usleep (identity->sleep_time);
|
|
||||||
|
|
||||||
gst_buffer_ref (inbuf);
|
|
||||||
*outbuf = inbuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*outbuf = gst_buffer_make_writable (inbuf);
|
||||||
|
/* inbuf is no longer usable */
|
||||||
|
|
||||||
|
if (identity->datarate > 0) {
|
||||||
|
GstClockTime time = identity->offset * GST_SECOND / identity->datarate;
|
||||||
|
|
||||||
|
GST_BUFFER_TIMESTAMP (*outbuf) = time;
|
||||||
|
GST_BUFFER_DURATION (*outbuf) =
|
||||||
|
GST_BUFFER_SIZE (*outbuf) * GST_SECOND / identity->datarate;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
|
||||||
|
*outbuf);
|
||||||
|
|
||||||
|
if (identity->sync) {
|
||||||
|
GstClock *clock;
|
||||||
|
GstClockReturn cret;
|
||||||
|
|
||||||
|
clock = GST_ELEMENT (identity)->clock;
|
||||||
|
|
||||||
|
if (clock) {
|
||||||
|
/* save id if we need to unlock */
|
||||||
|
/* FIXME: actually unlock this somewhere if the state changes */
|
||||||
|
GST_LOCK (identity);
|
||||||
|
identity->clock_id = gst_clock_new_single_shot_id (clock,
|
||||||
|
GST_BUFFER_TIMESTAMP (*outbuf) + GST_ELEMENT (identity)->base_time);
|
||||||
|
GST_UNLOCK (identity);
|
||||||
|
cret = gst_clock_id_wait (identity->clock_id, NULL);
|
||||||
|
GST_LOCK (identity);
|
||||||
|
if (identity->clock_id) {
|
||||||
|
gst_clock_id_unref (identity->clock_id);
|
||||||
|
identity->clock_id = NULL;
|
||||||
|
}
|
||||||
|
GST_UNLOCK (identity);
|
||||||
|
if (cret == GST_CLOCK_UNSCHEDULED)
|
||||||
|
ret = GST_FLOW_UNEXPECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
identity->offset += GST_BUFFER_SIZE (*outbuf);
|
||||||
|
|
||||||
|
if (identity->sleep_time && ret == GST_FLOW_OK)
|
||||||
|
g_usleep (identity->sleep_time);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,9 +381,6 @@ gst_identity_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_SILENT:
|
case PROP_SILENT:
|
||||||
identity->silent = g_value_get_boolean (value);
|
identity->silent = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
case PROP_DUPLICATE:
|
|
||||||
identity->duplicate = g_value_get_uint (value);
|
|
||||||
break;
|
|
||||||
case PROP_DUMP:
|
case PROP_DUMP:
|
||||||
identity->dump = g_value_get_boolean (value);
|
identity->dump = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
@ -415,9 +417,6 @@ gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_SLEEP_TIME:
|
case PROP_SLEEP_TIME:
|
||||||
g_value_set_uint (value, identity->sleep_time);
|
g_value_set_uint (value, identity->sleep_time);
|
||||||
break;
|
break;
|
||||||
case PROP_DUPLICATE:
|
|
||||||
g_value_set_uint (value, identity->duplicate);
|
|
||||||
break;
|
|
||||||
case PROP_ERROR_AFTER:
|
case PROP_ERROR_AFTER:
|
||||||
g_value_set_int (value, identity->error_after);
|
g_value_set_int (value, identity->error_after);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -48,7 +48,7 @@ typedef struct _GstIdentityClass GstIdentityClass;
|
||||||
struct _GstIdentity {
|
struct _GstIdentity {
|
||||||
GstBaseTransform element;
|
GstBaseTransform element;
|
||||||
|
|
||||||
guint duplicate;
|
GstClockID clock_id;
|
||||||
gint error_after;
|
gint error_after;
|
||||||
gfloat drop_probability;
|
gfloat drop_probability;
|
||||||
gint datarate;
|
gint datarate;
|
||||||
|
|
|
@ -54,9 +54,7 @@ exec guile --debug -l $0 -e main -- "$@"
|
||||||
;; second argument, rather deferring that calculation until stream-cdr
|
;; second argument, rather deferring that calculation until stream-cdr
|
||||||
;; is called. In that way all times are actually infinite series.
|
;; is called. In that way all times are actually infinite series.
|
||||||
;;
|
;;
|
||||||
;; Knobs: sample rate, send delay, receive delay, send noise, receive
|
;; Usage: See network-clock.scm --help.
|
||||||
;; noise, queue length, rate of remote clock, rate of local clock. See
|
|
||||||
;; network-clock.scm --help.
|
|
||||||
;;
|
;;
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
|
|
|
@ -54,9 +54,7 @@ exec guile --debug -l $0 -e main -- "$@"
|
||||||
;; second argument, rather deferring that calculation until stream-cdr
|
;; second argument, rather deferring that calculation until stream-cdr
|
||||||
;; is called. In that way all times are actually infinite series.
|
;; is called. In that way all times are actually infinite series.
|
||||||
;;
|
;;
|
||||||
;; Knobs: sample rate, send delay, receive delay, send noise, receive
|
;; Usage: See network-clock.scm --help.
|
||||||
;; noise, queue length, rate of remote clock, rate of local clock. See
|
|
||||||
;; network-clock.scm --help.
|
|
||||||
;;
|
;;
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue