mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-04 13:32:29 +00:00
docs/design/part-block.txt: Fix typo.
Original commit message from CVS: * docs/design/part-block.txt: Fix typo. * docs/design/part-element-transform.txt: Add notes about why transform needs to know input/output sizes. Add some issues that need to be solved. Add some more use cases. * tests/check/libs/test_transform.c: (gst_test_trans_base_init), (gst_test_trans_class_init), (result_sink_chain), (result_buffer_alloc), (gst_test_trans_new), (gst_test_trans_free), (gst_test_trans_push), (gst_test_trans_pop): * tests/check/libs/transform1.c: (buffer_alloc_pt1), (set_caps_pt1), (GST_START_TEST), (set_caps_pt2), (transform_ip_1), (set_caps_1), (set_caps_ct1), (transform_ct1), (transform_caps_ct1), (transform_size_ct1), (buffer_alloc_ct1), (gst_basetransform_suite): Add suport for different pad templates and buffer-alloc. Add more checks for caps and buffer-alloc. Add checks for proxy buffer alloc. Add unit test for copy transform.
This commit is contained in:
parent
7dd35f98f7
commit
23d8478698
5 changed files with 613 additions and 16 deletions
24
ChangeLog
24
ChangeLog
|
@ -1,3 +1,27 @@
|
|||
2008-06-25 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||
|
||||
* docs/design/part-block.txt:
|
||||
Fix typo.
|
||||
|
||||
* docs/design/part-element-transform.txt:
|
||||
Add notes about why transform needs to know input/output sizes.
|
||||
Add some issues that need to be solved.
|
||||
Add some more use cases.
|
||||
|
||||
* tests/check/libs/test_transform.c: (gst_test_trans_base_init),
|
||||
(gst_test_trans_class_init), (result_sink_chain),
|
||||
(result_buffer_alloc), (gst_test_trans_new), (gst_test_trans_free),
|
||||
(gst_test_trans_push), (gst_test_trans_pop):
|
||||
* tests/check/libs/transform1.c: (buffer_alloc_pt1),
|
||||
(set_caps_pt1), (GST_START_TEST), (set_caps_pt2), (transform_ip_1),
|
||||
(set_caps_1), (set_caps_ct1), (transform_ct1),
|
||||
(transform_caps_ct1), (transform_size_ct1), (buffer_alloc_ct1),
|
||||
(gst_basetransform_suite):
|
||||
Add suport for different pad templates and buffer-alloc.
|
||||
Add more checks for caps and buffer-alloc.
|
||||
Add checks for proxy buffer alloc.
|
||||
Add unit test for copy transform.
|
||||
|
||||
2008-06-24 Tim-Philipp Müller <tim.muller at collabora co uk>
|
||||
|
||||
Patch by: Luc Pionchon <luc.pionchon@nokia.com>
|
||||
|
|
|
@ -125,7 +125,7 @@ Use cases:
|
|||
pipeline.
|
||||
|
||||
1) block element1 src pad. This can be done async.
|
||||
2) wait for block to happen. at this point nothing flowing between
|
||||
2) wait for block to happen. at that point nothing is flowing between
|
||||
element1 and element2 and nothing will flow until unblocked.
|
||||
3) unlink element1 and element2
|
||||
4) optional step: make sure data is flushed out of element2:
|
||||
|
|
|
@ -397,3 +397,80 @@ Negotiation
|
|||
<----------------------------------| |
|
||||
| | |
|
||||
|
||||
In order to perform passthrough buffer-alloc or pad-alloc, we need to be able
|
||||
to get the size of the output buffer after the transform.
|
||||
|
||||
For passthrough buffer-alloc, this is trivial: the input size equals the output
|
||||
size.
|
||||
|
||||
For the copy transform or the in-place transform we need additional function to
|
||||
retrieve the size. There are two functions:
|
||||
|
||||
- transform_size()
|
||||
|
||||
Given a caps and a size on one pad, and a caps on the other pad, calculate
|
||||
the size of the other buffer. This function is able to perform all size
|
||||
transforms and is the prefered method of transforming a size.
|
||||
|
||||
- get_unit_size()
|
||||
|
||||
When the input size and output size are always a multiple of eachother
|
||||
(audio conversion, ..) we can define a more simple get_unit_size() function.
|
||||
The transform will use this function to get the same amount of units in the
|
||||
source and destination buffers.
|
||||
|
||||
For performance reasons, the mapping between caps and size is kept in a cache.
|
||||
|
||||
|
||||
Issues
|
||||
------
|
||||
|
||||
passthrough and in-place transforms (with writable buffers) never need to
|
||||
perform a pad-alloc on the srcpad. This means that if upstream negotiation
|
||||
happens, the transform element will never know about it.
|
||||
|
||||
The transform element will keep therefore track of the allocation pattern of
|
||||
the peer elements. We can see the following cases:
|
||||
|
||||
- upstream peer calls buffer-alloc on the sinkpad of the transform. In some
|
||||
cases (see above) this call gets proxied or not.
|
||||
|
||||
- upstream peer does never call buffer-alloc.
|
||||
|
||||
We will keeps state about this allocation pattern and perform the following in
|
||||
each case respectively:
|
||||
|
||||
- Upstream calls buffer-alloc: In passthrough and (some) in-place we proxy
|
||||
this call onto the downstream element. If the caps are changed, we mark
|
||||
a flag that we will require a new pad-alloc for the output of the next
|
||||
output buffer.
|
||||
|
||||
- upstream peer does not call buffer-alloc: We always perform a pad-alloc
|
||||
when processing buffers. We can further optimize by only looking at the
|
||||
returned caps instead of doing a full, needless buffer copy.
|
||||
|
||||
|
||||
Use cases
|
||||
---------
|
||||
|
||||
videotestsrc ! ximagesink
|
||||
|
||||
- resizing happens because videotestsrc performs pad-alloc.
|
||||
|
||||
videotestsrc peer-alloc=0 ! ximagesink
|
||||
|
||||
- resizing cannot happen because videotestsrc never performs pad-alloc.
|
||||
|
||||
videotestsrc ! videoscale ! ximagesink
|
||||
|
||||
- videoscale is initially configured in passthrough mode, pad-alloc from
|
||||
videotestsrc is proxied through videoscale.
|
||||
- pad-alloc will renegotiate a new size in videotestsrc.
|
||||
|
||||
videotestsrc peer-alloc=0 ! videoscale ! ximagesink
|
||||
|
||||
- videoscale is initially configured in passthrough mode.
|
||||
- videoscale performs pad-alloc because no buffer-alloc is called on the
|
||||
sinkpad
|
||||
- resizing the videosink makes videoscale perform the scaling.
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ typedef struct
|
|||
GList *buffers;
|
||||
GstElement *trans;
|
||||
GstBaseTransformClass *klass;
|
||||
|
||||
GstPadBufferAllocFunction buffer_alloc;
|
||||
} TestTransData;
|
||||
|
||||
static GstStaticPadTemplate gst_test_trans_src_template =
|
||||
|
@ -56,6 +58,21 @@ struct _GstTestTransClass
|
|||
GST_BOILERPLATE (GstTestTrans, gst_test_trans, GstBaseTransform,
|
||||
GST_TYPE_BASE_TRANSFORM);
|
||||
|
||||
static GstFlowReturn (*klass_transform) (GstBaseTransform * trans,
|
||||
GstBuffer * inbuf, GstBuffer * outbuf) = NULL;
|
||||
static GstFlowReturn (*klass_transform_ip) (GstBaseTransform * trans,
|
||||
GstBuffer * buf) = NULL;
|
||||
static gboolean (*klass_set_caps) (GstBaseTransform * trans, GstCaps * incaps,
|
||||
GstCaps * outcaps) = NULL;
|
||||
static GstCaps *(*klass_transform_caps) (GstBaseTransform * trans,
|
||||
GstPadDirection direction, GstCaps * caps) = NULL;
|
||||
static gboolean (*klass_transform_size) (GstBaseTransform * trans,
|
||||
GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps,
|
||||
guint * othersize) = NULL;
|
||||
|
||||
static GstStaticPadTemplate *sink_template = &gst_test_trans_sink_template;
|
||||
static GstStaticPadTemplate *src_template = &gst_test_trans_src_template;
|
||||
|
||||
static void
|
||||
gst_test_trans_base_init (gpointer g_class)
|
||||
{
|
||||
|
@ -67,18 +84,11 @@ gst_test_trans_base_init (gpointer g_class)
|
|||
"Filter/Test", "Test transform", "Wim Taymans <wim.taymans@gmail.com>");
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&gst_test_trans_sink_template));
|
||||
gst_static_pad_template_get (sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&gst_test_trans_src_template));
|
||||
gst_static_pad_template_get (src_template));
|
||||
}
|
||||
|
||||
static GstFlowReturn (*klass_transform) (GstBaseTransform * trans,
|
||||
GstBuffer * inbuf, GstBuffer * outbuf) = NULL;
|
||||
static GstFlowReturn (*klass_transform_ip) (GstBaseTransform * trans,
|
||||
GstBuffer * buf) = NULL;
|
||||
static gboolean (*klass_set_caps) (GstBaseTransform * trans, GstCaps * incaps,
|
||||
GstCaps * outcaps) = NULL;
|
||||
|
||||
static void
|
||||
gst_test_trans_class_init (GstTestTransClass * klass)
|
||||
{
|
||||
|
@ -90,6 +100,8 @@ gst_test_trans_class_init (GstTestTransClass * klass)
|
|||
|
||||
trans_class->transform_ip = klass_transform_ip;
|
||||
trans_class->transform = klass_transform;
|
||||
trans_class->transform_caps = klass_transform_caps;
|
||||
trans_class->transform_size = klass_transform_size;
|
||||
trans_class->set_caps = klass_set_caps;
|
||||
}
|
||||
|
||||
|
@ -116,23 +128,52 @@ result_sink_chain (GstPad * pad, GstBuffer * buffer)
|
|||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
result_buffer_alloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
|
||||
GstBuffer ** buf)
|
||||
{
|
||||
GstFlowReturn res;
|
||||
TestTransData *data;
|
||||
|
||||
data = gst_pad_get_element_private (pad);
|
||||
|
||||
if (data->buffer_alloc) {
|
||||
res = data->buffer_alloc (pad, offset, size, caps, buf);
|
||||
} else {
|
||||
*buf = gst_buffer_new_and_alloc (size);
|
||||
gst_buffer_set_caps (*buf, caps);
|
||||
res = GST_FLOW_OK;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static TestTransData *
|
||||
gst_test_trans_new (void)
|
||||
{
|
||||
TestTransData *res;
|
||||
GstPad *tmp;
|
||||
GstPadTemplate *templ;
|
||||
|
||||
res = g_new0 (TestTransData, 1);
|
||||
res->trans = g_object_new (GST_TYPE_TEST_TRANS, NULL);
|
||||
res->srcpad =
|
||||
gst_pad_new_from_static_template (&gst_test_trans_src_template, "src");
|
||||
res->sinkpad =
|
||||
gst_pad_new_from_static_template (&gst_test_trans_sink_template, "sink");
|
||||
|
||||
templ = gst_static_pad_template_get (sink_template);
|
||||
templ->direction = GST_PAD_SRC;
|
||||
res->srcpad = gst_pad_new_from_template (templ, "src");
|
||||
gst_object_unref (templ);
|
||||
|
||||
templ = gst_static_pad_template_get (src_template);
|
||||
templ->direction = GST_PAD_SINK;
|
||||
res->sinkpad = gst_pad_new_from_template (templ, "sink");
|
||||
gst_object_unref (templ);
|
||||
|
||||
res->klass = GST_BASE_TRANSFORM_GET_CLASS (res->trans);
|
||||
|
||||
gst_test_trans_set_data (GST_TEST_TRANS (res->trans), res);
|
||||
gst_pad_set_element_private (res->sinkpad, res);
|
||||
|
||||
gst_pad_set_bufferalloc_function (res->sinkpad, result_buffer_alloc);
|
||||
gst_pad_set_chain_function (res->sinkpad, result_sink_chain);
|
||||
|
||||
tmp = gst_element_get_static_pad (res->trans, "sink");
|
||||
|
|
|
@ -31,6 +31,35 @@
|
|||
|
||||
#include "test_transform.c"
|
||||
|
||||
static gboolean buffer_alloc_pt1_called;
|
||||
|
||||
static GstFlowReturn
|
||||
buffer_alloc_pt1 (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
|
||||
GstBuffer ** buf)
|
||||
{
|
||||
GST_DEBUG_OBJECT (pad, "buffer_alloc called %" G_GUINT64_FORMAT ", %u, %"
|
||||
GST_PTR_FORMAT, offset, size, caps);
|
||||
|
||||
buffer_alloc_pt1_called = TRUE;
|
||||
|
||||
*buf = gst_buffer_new_and_alloc (size);
|
||||
gst_buffer_set_caps (*buf, caps);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static gboolean set_caps_pt1_called;
|
||||
|
||||
static gboolean
|
||||
set_caps_pt1 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps)
|
||||
{
|
||||
GST_DEBUG_OBJECT (trans, "set_caps called");
|
||||
|
||||
set_caps_pt1_called = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* basic passthrough, we don't have any transform functions so we can only
|
||||
* perform passthrough. We also don't have caps, which is fine */
|
||||
GST_START_TEST (basetransform_chain_pt1)
|
||||
|
@ -38,13 +67,25 @@ GST_START_TEST (basetransform_chain_pt1)
|
|||
TestTransData *trans;
|
||||
GstBuffer *buffer;
|
||||
GstFlowReturn res;
|
||||
GstCaps *caps;
|
||||
|
||||
klass_set_caps = set_caps_pt1;
|
||||
trans = gst_test_trans_new ();
|
||||
trans->buffer_alloc = buffer_alloc_pt1;
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "buffer without caps, size 20");
|
||||
|
||||
buffer = gst_buffer_new_and_alloc (20);
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
set_caps_pt1_called = FALSE;;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
#ifdef FAILING_TESTS
|
||||
/* FIXME, passthough without pad-alloc, do pad-alloc on the srcpad */
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
#endif
|
||||
fail_unless (set_caps_pt1_called == FALSE);
|
||||
|
||||
buffer = gst_test_trans_pop (trans);
|
||||
fail_unless (buffer != NULL);
|
||||
|
@ -54,9 +95,18 @@ GST_START_TEST (basetransform_chain_pt1)
|
|||
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "buffer without caps, size 10");
|
||||
|
||||
buffer = gst_buffer_new_and_alloc (10);
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
set_caps_pt1_called = FALSE;;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
#ifdef FAILING_TESTS
|
||||
/* FIXME, passthough without pad-alloc, do pad-alloc on the srcpad */
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
#endif
|
||||
fail_unless (set_caps_pt1_called == FALSE);
|
||||
|
||||
buffer = gst_test_trans_pop (trans);
|
||||
fail_unless (buffer != NULL);
|
||||
|
@ -66,11 +116,59 @@ GST_START_TEST (basetransform_chain_pt1)
|
|||
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* proxy buffer-alloc without caps */
|
||||
GST_DEBUG_OBJECT (trans, "alloc without caps, size 20");
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
set_caps_pt1_called = FALSE;;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, NULL, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
fail_unless (set_caps_pt1_called == FALSE);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* with caps buffer */
|
||||
GST_DEBUG_OBJECT (trans, "alloc with caps, size 10");
|
||||
|
||||
caps = gst_caps_new_simple ("foo/x-bar", NULL);
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
set_caps_pt1_called = FALSE;;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, caps, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
fail_unless (set_caps_pt1_called == FALSE);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* once more */
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
set_caps_pt1_called = FALSE;;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, caps, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
fail_unless (set_caps_pt1_called == FALSE);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
gst_caps_unref (caps);
|
||||
|
||||
gst_test_trans_free (trans);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static gboolean set_caps_pt2_called;
|
||||
|
||||
static gboolean
|
||||
set_caps_pt2 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps)
|
||||
{
|
||||
GST_DEBUG_OBJECT (trans, "set_caps called");
|
||||
|
||||
set_caps_pt2_called = TRUE;
|
||||
|
||||
fail_unless (gst_caps_is_equal (incaps, outcaps));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* basic passthrough, we don't have any transform functions so we can only
|
||||
* perform passthrough with same caps */
|
||||
GST_START_TEST (basetransform_chain_pt2)
|
||||
|
@ -80,16 +178,27 @@ GST_START_TEST (basetransform_chain_pt2)
|
|||
GstCaps *caps;
|
||||
GstFlowReturn res;
|
||||
|
||||
klass_set_caps = set_caps_pt2;
|
||||
trans = gst_test_trans_new ();
|
||||
trans->buffer_alloc = buffer_alloc_pt1;
|
||||
|
||||
/* first buffer */
|
||||
caps = gst_caps_new_simple ("foo/x-bar", NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "buffer with caps, size 20");
|
||||
|
||||
buffer = gst_buffer_new_and_alloc (20);
|
||||
gst_buffer_set_caps (buffer, caps);
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
set_caps_pt2_called = FALSE;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
#ifdef FAILING_TESTS
|
||||
/* FIXME, passthough without pad-alloc, do pad-alloc on the srcpad */
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
#endif
|
||||
fail_unless (set_caps_pt2_called == TRUE);
|
||||
|
||||
buffer = gst_test_trans_pop (trans);
|
||||
fail_unless (buffer != NULL);
|
||||
|
@ -97,16 +206,37 @@ GST_START_TEST (basetransform_chain_pt2)
|
|||
fail_unless (GST_BUFFER_CAPS (buffer) == caps);
|
||||
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* with caps buffer */
|
||||
GST_DEBUG_OBJECT (trans, "alloc with caps, size 20");
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
set_caps_pt2_called = FALSE;;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, caps, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
fail_unless (set_caps_pt2_called == FALSE);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* second buffer, renegotiates, keeps extra type arg in caps */
|
||||
caps = gst_caps_new_simple ("foo/x-bar", "type", G_TYPE_INT, 1, NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "buffer with caps, size 10");
|
||||
|
||||
buffer = gst_buffer_new_and_alloc (10);
|
||||
gst_buffer_set_caps (buffer, caps);
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
set_caps_pt2_called = FALSE;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
#ifdef FAILING_TESTS
|
||||
/* FIXME, passthough without pad-alloc, do pad-alloc on the srcpad */
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
#endif
|
||||
fail_unless (set_caps_pt2_called == TRUE);
|
||||
|
||||
buffer = gst_test_trans_pop (trans);
|
||||
fail_unless (buffer != NULL);
|
||||
|
@ -114,6 +244,33 @@ GST_START_TEST (basetransform_chain_pt2)
|
|||
fail_unless (GST_BUFFER_CAPS (buffer) == caps);
|
||||
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* with caps buffer */
|
||||
GST_DEBUG_OBJECT (trans, "alloc with caps, size 20");
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
set_caps_pt2_called = FALSE;;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, caps, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
fail_unless (set_caps_pt2_called == FALSE);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* with caps that is a superset */
|
||||
caps = gst_caps_new_simple ("foo/x-bar", NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "alloc with superset caps, size 20");
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
set_caps_pt2_called = FALSE;;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, caps, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
fail_unless (set_caps_pt2_called == FALSE);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
gst_caps_unref (caps);
|
||||
|
||||
gst_test_trans_free (trans);
|
||||
|
@ -147,21 +304,31 @@ GST_START_TEST (basetransform_chain_ip1)
|
|||
|
||||
klass_transform_ip = transform_ip_1;
|
||||
trans = gst_test_trans_new ();
|
||||
trans->buffer_alloc = buffer_alloc_pt1;
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "buffer without caps, size 20");
|
||||
|
||||
buffer = gst_buffer_new_and_alloc (20);
|
||||
|
||||
transform_ip_1_called = FALSE;;
|
||||
transform_ip_1_writable = TRUE;;
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (transform_ip_1_called == TRUE);
|
||||
fail_unless (transform_ip_1_writable == TRUE);
|
||||
#ifdef FAILING_TESTS
|
||||
/* FIXME, in-place without pad-alloc, do pad-alloc on the srcpad */
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
#endif
|
||||
|
||||
buffer = gst_test_trans_pop (trans);
|
||||
fail_unless (buffer != NULL);
|
||||
fail_unless (GST_BUFFER_SIZE (buffer) == 20);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "buffer without caps extra ref, size 20");
|
||||
|
||||
buffer = gst_buffer_new_and_alloc (20);
|
||||
/* take additional ref to make it non-writable */
|
||||
gst_buffer_ref (buffer);
|
||||
|
@ -170,11 +337,13 @@ GST_START_TEST (basetransform_chain_ip1)
|
|||
|
||||
transform_ip_1_called = FALSE;;
|
||||
transform_ip_1_writable = FALSE;;
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (transform_ip_1_called == TRUE);
|
||||
/* copy should have been taken */
|
||||
/* copy should have been taken with pad-alloc */
|
||||
fail_unless (transform_ip_1_writable == TRUE);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
/* after push, get rid of the final ref we had */
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
|
@ -186,6 +355,15 @@ GST_START_TEST (basetransform_chain_ip1)
|
|||
fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* with caps buffer */
|
||||
GST_DEBUG_OBJECT (trans, "alloc without caps, size 20");
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, NULL, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
gst_test_trans_free (trans);
|
||||
}
|
||||
|
||||
|
@ -225,33 +403,67 @@ GST_START_TEST (basetransform_chain_ip2)
|
|||
klass_set_caps = set_caps_1;
|
||||
|
||||
trans = gst_test_trans_new ();
|
||||
trans->buffer_alloc = buffer_alloc_pt1;
|
||||
|
||||
/* with caps buffer */
|
||||
GST_DEBUG_OBJECT (trans, "alloc without caps, size 20");
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, NULL, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
fail_unless (GST_BUFFER_SIZE (buffer) == 20);
|
||||
fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
caps = gst_caps_new_simple ("foo/x-bar", NULL);
|
||||
|
||||
/* with caps buffer */
|
||||
GST_DEBUG_OBJECT (trans, "alloc with caps, size 20");
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, caps, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
fail_unless (GST_BUFFER_SIZE (buffer) == 20);
|
||||
fail_unless (GST_BUFFER_CAPS (buffer) == caps);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* first try to push a buffer without caps, this should fail */
|
||||
buffer = gst_buffer_new_and_alloc (20);
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "buffer without caps, size 20");
|
||||
|
||||
transform_ip_1_called = FALSE;;
|
||||
transform_ip_1_writable = FALSE;;
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
set_caps_1_called = FALSE;;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
|
||||
fail_unless (transform_ip_1_called == FALSE);
|
||||
fail_unless (transform_ip_1_writable == FALSE);
|
||||
fail_unless (set_caps_1_called == FALSE);
|
||||
fail_unless (buffer_alloc_pt1_called == FALSE);
|
||||
|
||||
/* try to push a buffer with caps */
|
||||
GST_DEBUG_OBJECT (trans, "buffer with caps, size 20");
|
||||
|
||||
buffer = gst_buffer_new_and_alloc (20);
|
||||
gst_buffer_set_caps (buffer, caps);
|
||||
|
||||
transform_ip_1_called = FALSE;
|
||||
transform_ip_1_writable = FALSE;
|
||||
set_caps_1_called = FALSE;;
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (transform_ip_1_called == TRUE);
|
||||
fail_unless (transform_ip_1_writable == TRUE);
|
||||
fail_unless (set_caps_1_called == TRUE);
|
||||
#ifdef FAILING_TESTS
|
||||
/* FIXME, in-place without pad-alloc, do pad-alloc on the srcpad */
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
#endif
|
||||
|
||||
buffer = gst_test_trans_pop (trans);
|
||||
fail_unless (buffer != NULL);
|
||||
|
@ -259,6 +471,17 @@ GST_START_TEST (basetransform_chain_ip2)
|
|||
fail_unless (GST_BUFFER_CAPS (buffer) == caps);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* with caps buffer */
|
||||
GST_DEBUG_OBJECT (trans, "alloc with caps, size 20");
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, caps, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "buffer with caps extra ref, size 20");
|
||||
|
||||
buffer = gst_buffer_new_and_alloc (20);
|
||||
gst_buffer_set_caps (buffer, caps);
|
||||
/* take additional ref to make it non-writable */
|
||||
|
@ -268,10 +491,12 @@ GST_START_TEST (basetransform_chain_ip2)
|
|||
|
||||
transform_ip_1_called = FALSE;;
|
||||
transform_ip_1_writable = FALSE;;
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (transform_ip_1_called == TRUE);
|
||||
fail_unless (transform_ip_1_writable == TRUE);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
/* after push, get rid of the final ref we had */
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
|
@ -284,14 +509,243 @@ GST_START_TEST (basetransform_chain_ip2)
|
|||
fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* with caps buffer */
|
||||
GST_DEBUG_OBJECT (trans, "alloc with caps, size 20");
|
||||
|
||||
buffer_alloc_pt1_called = FALSE;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, caps, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (buffer_alloc_pt1_called == TRUE);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
gst_caps_unref (caps);
|
||||
|
||||
trans->klass->transform_ip = NULL;
|
||||
gst_test_trans_free (trans);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static GstStaticPadTemplate sink_template_ct1 = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("baz/x-foo")
|
||||
);
|
||||
|
||||
static gboolean set_caps_ct1_called;
|
||||
|
||||
static gboolean
|
||||
set_caps_ct1 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps)
|
||||
{
|
||||
GstCaps *caps1, *caps2;
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "set_caps called");
|
||||
|
||||
caps1 = gst_caps_new_simple ("baz/x-foo", NULL);
|
||||
caps2 = gst_caps_new_simple ("foo/x-bar", NULL);
|
||||
|
||||
fail_unless (gst_caps_is_equal (incaps, caps1));
|
||||
fail_unless (gst_caps_is_equal (outcaps, caps2));
|
||||
|
||||
set_caps_ct1_called = TRUE;;
|
||||
|
||||
gst_caps_unref (caps1);
|
||||
gst_caps_unref (caps2);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean transform_ct_1_called;
|
||||
static gboolean transform_ct_1_writable;
|
||||
|
||||
static GstFlowReturn
|
||||
transform_ct1 (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
|
||||
{
|
||||
transform_ct_1_called = TRUE;
|
||||
transform_ct_1_writable = gst_buffer_is_writable (out);
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "writable: %d", transform_ct_1_writable);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
transform_caps_ct1 (GstBaseTransform * trans, GstPadDirection dir,
|
||||
GstCaps * caps)
|
||||
{
|
||||
GstCaps *res;
|
||||
|
||||
if (dir == GST_PAD_SINK) {
|
||||
res = gst_caps_new_simple ("foo/x-bar", NULL);
|
||||
} else {
|
||||
res = gst_caps_new_simple ("baz/x-foo", NULL);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
transform_size_ct1 (GstBaseTransform * trans, GstPadDirection direction,
|
||||
GstCaps * caps, guint size, GstCaps * othercaps, guint * othersize)
|
||||
{
|
||||
if (direction == GST_PAD_SINK) {
|
||||
*othersize = size * 2;
|
||||
} else {
|
||||
*othersize = size / 2;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean buffer_alloc_ct1_called;
|
||||
|
||||
static GstFlowReturn
|
||||
buffer_alloc_ct1 (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
|
||||
GstBuffer ** buf)
|
||||
{
|
||||
GstCaps *outcaps;
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "buffer_alloc called %" G_GUINT64_FORMAT ", %u, %"
|
||||
GST_PTR_FORMAT, offset, size, caps);
|
||||
|
||||
buffer_alloc_ct1_called = TRUE;
|
||||
|
||||
outcaps = gst_caps_new_simple ("foo/x-bar", NULL);
|
||||
fail_unless (gst_caps_is_equal (outcaps, caps));
|
||||
gst_caps_unref (outcaps);
|
||||
|
||||
*buf = gst_buffer_new_and_alloc (size);
|
||||
gst_buffer_set_caps (*buf, caps);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
/* basic copy-transform, check if the transform function is called,
|
||||
* buffer should be writable. we also set a setcaps function and
|
||||
* see if it's called. */
|
||||
GST_START_TEST (basetransform_chain_ct1)
|
||||
{
|
||||
TestTransData *trans;
|
||||
GstBuffer *buffer;
|
||||
GstFlowReturn res;
|
||||
GstCaps *incaps, *outcaps;
|
||||
|
||||
sink_template = &sink_template_ct1;
|
||||
klass_transform = transform_ct1;
|
||||
klass_set_caps = set_caps_ct1;
|
||||
klass_transform_caps = transform_caps_ct1;
|
||||
klass_transform_size = transform_size_ct1;
|
||||
|
||||
trans = gst_test_trans_new ();
|
||||
trans->buffer_alloc = buffer_alloc_ct1;
|
||||
|
||||
incaps = gst_caps_new_simple ("baz/x-foo", NULL);
|
||||
outcaps = gst_caps_new_simple ("foo/x-bar", NULL);
|
||||
|
||||
#if 0
|
||||
/* without caps buffer, I think this should fail */
|
||||
GST_DEBUG_OBJECT (trans, "alloc without caps, size 20");
|
||||
|
||||
buffer_alloc_ct1_called = FALSE;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, NULL, &buffer);
|
||||
fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
|
||||
/* should not call pad-alloc because the caps and sizes are different */
|
||||
fail_unless (buffer_alloc_ct1_called == FALSE);
|
||||
#endif
|
||||
|
||||
/* with wrong caps buffer */
|
||||
GST_DEBUG_OBJECT (trans, "alloc with wrong caps, size 20");
|
||||
|
||||
buffer_alloc_ct1_called = FALSE;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, outcaps, &buffer);
|
||||
fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
|
||||
fail_unless (buffer_alloc_ct1_called == TRUE);
|
||||
|
||||
/* with caps buffer */
|
||||
GST_DEBUG_OBJECT (trans, "alloc with caps, size 20");
|
||||
|
||||
buffer_alloc_ct1_called = FALSE;
|
||||
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, incaps, &buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
/* should not call pad-alloc because the caps and sizes are different */
|
||||
fail_unless (buffer_alloc_ct1_called == FALSE);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* first try to push a buffer without caps, this should fail */
|
||||
buffer = gst_buffer_new_and_alloc (20);
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "buffer without caps");
|
||||
|
||||
transform_ct_1_called = FALSE;;
|
||||
transform_ct_1_writable = FALSE;;
|
||||
set_caps_ct1_called = FALSE;;
|
||||
buffer_alloc_ct1_called = FALSE;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
|
||||
fail_unless (transform_ct_1_called == FALSE);
|
||||
fail_unless (transform_ct_1_writable == FALSE);
|
||||
fail_unless (set_caps_ct1_called == FALSE);
|
||||
fail_unless (buffer_alloc_ct1_called == FALSE);
|
||||
|
||||
/* try to push a buffer with caps */
|
||||
buffer = gst_buffer_new_and_alloc (20);
|
||||
gst_buffer_set_caps (buffer, incaps);
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps);
|
||||
|
||||
transform_ct_1_called = FALSE;
|
||||
transform_ct_1_writable = FALSE;
|
||||
set_caps_ct1_called = FALSE;;
|
||||
buffer_alloc_ct1_called = FALSE;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (transform_ct_1_called == TRUE);
|
||||
fail_unless (transform_ct_1_writable == TRUE);
|
||||
fail_unless (set_caps_ct1_called == TRUE);
|
||||
fail_unless (buffer_alloc_ct1_called == TRUE);
|
||||
|
||||
buffer = gst_test_trans_pop (trans);
|
||||
fail_unless (buffer != NULL);
|
||||
fail_unless (GST_BUFFER_SIZE (buffer) == 40);
|
||||
fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
buffer = gst_buffer_new_and_alloc (20);
|
||||
gst_buffer_set_caps (buffer, incaps);
|
||||
/* take additional ref to make it non-writable */
|
||||
gst_buffer_ref (buffer);
|
||||
|
||||
fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 2);
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps);
|
||||
|
||||
transform_ct_1_called = FALSE;;
|
||||
transform_ct_1_writable = FALSE;;
|
||||
buffer_alloc_ct1_called = FALSE;
|
||||
res = gst_test_trans_push (trans, buffer);
|
||||
fail_unless (res == GST_FLOW_OK);
|
||||
fail_unless (transform_ct_1_called == TRUE);
|
||||
fail_unless (transform_ct_1_writable == TRUE);
|
||||
fail_unless (buffer_alloc_ct1_called == TRUE);
|
||||
/* after push, get rid of the final ref we had */
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
buffer = gst_test_trans_pop (trans);
|
||||
fail_unless (buffer != NULL);
|
||||
fail_unless (GST_BUFFER_SIZE (buffer) == 40);
|
||||
fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
|
||||
|
||||
/* output buffer has refcount 1 */
|
||||
fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
gst_caps_unref (incaps);
|
||||
gst_caps_unref (outcaps);
|
||||
|
||||
gst_test_trans_free (trans);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
static Suite *
|
||||
gst_basetransform_suite (void)
|
||||
{
|
||||
|
@ -303,6 +757,7 @@ gst_basetransform_suite (void)
|
|||
tcase_add_test (tc, basetransform_chain_pt2);
|
||||
tcase_add_test (tc, basetransform_chain_ip1);
|
||||
tcase_add_test (tc, basetransform_chain_ip2);
|
||||
tcase_add_test (tc, basetransform_chain_ct1);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue