mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
docs/libs/gstreamer-libs-sections.txt: API: addition: gst_adapter_take_buffer()
Original commit message from CVS: * docs/libs/gstreamer-libs-sections.txt: API: addition: gst_adapter_take_buffer() * libs/gst/base/gstadapter.c: (gst_adapter_push), (gst_adapter_peek), (gst_adapter_take), (gst_adapter_take_buffer), (gst_adapter_available_fast): * libs/gst/base/gstadapter.h: Prepare for optimizing the hell out of this hugely inefficient piece of code. Added gst_adapter_take_buffer() so we can at least start thinking about subbuffering and merging. Added some comments. * tests/check/Makefile.am: * tests/check/libs/adapter.c: (GST_START_TEST), (gst_adapter_suite), (main): Added GstAdapter check.
This commit is contained in:
parent
cd16e10793
commit
4ceea3e44e
6 changed files with 291 additions and 5 deletions
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
||||||
|
2006-05-04 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* docs/libs/gstreamer-libs-sections.txt:
|
||||||
|
API: addition: gst_adapter_take_buffer()
|
||||||
|
|
||||||
|
* libs/gst/base/gstadapter.c: (gst_adapter_push),
|
||||||
|
(gst_adapter_peek), (gst_adapter_take), (gst_adapter_take_buffer),
|
||||||
|
(gst_adapter_available_fast):
|
||||||
|
* libs/gst/base/gstadapter.h:
|
||||||
|
Prepare for optimizing the hell out of this hugely inefficient
|
||||||
|
piece of code.
|
||||||
|
Added gst_adapter_take_buffer() so we can at least start thinking
|
||||||
|
about subbuffering and merging.
|
||||||
|
Added some comments.
|
||||||
|
|
||||||
|
* tests/check/Makefile.am:
|
||||||
|
* tests/check/libs/adapter.c: (GST_START_TEST),
|
||||||
|
(gst_adapter_suite), (main):
|
||||||
|
Added GstAdapter check.
|
||||||
|
|
||||||
2006-05-04 Wim Taymans <wim@fluendo.com>
|
2006-05-04 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* docs/design/part-overview.txt:
|
* docs/design/part-overview.txt:
|
||||||
|
|
|
@ -112,6 +112,7 @@ gst_adapter_flush
|
||||||
gst_adapter_available
|
gst_adapter_available
|
||||||
gst_adapter_available_fast
|
gst_adapter_available_fast
|
||||||
gst_adapter_take
|
gst_adapter_take
|
||||||
|
gst_adapter_take_buffer
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
GstAdapterClass
|
GstAdapterClass
|
||||||
GST_ADAPTER
|
GST_ADAPTER
|
||||||
|
|
|
@ -199,6 +199,8 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
|
||||||
g_return_if_fail (GST_IS_BUFFER (buf));
|
g_return_if_fail (GST_IS_BUFFER (buf));
|
||||||
|
|
||||||
adapter->size += GST_BUFFER_SIZE (buf);
|
adapter->size += GST_BUFFER_SIZE (buf);
|
||||||
|
/* FIXME, _append does not scale. Note: merging buffers at this
|
||||||
|
* point is premature. */
|
||||||
adapter->buflist = g_slist_append (adapter->buflist, buf);
|
adapter->buflist = g_slist_append (adapter->buflist, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +218,8 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
|
||||||
* of its chain function, the buffer will have an invalid data pointer after
|
* of its chain function, the buffer will have an invalid data pointer after
|
||||||
* your element flushes the bytes. In that case you should use
|
* your element flushes the bytes. In that case you should use
|
||||||
* gst_adapter_take(), which returns a freshly-allocated buffer that you can set
|
* gst_adapter_take(), which returns a freshly-allocated buffer that you can set
|
||||||
* as #GstBuffer malloc_data.
|
* as #GstBuffer malloc_data or the potentially more performant
|
||||||
|
* gst_adapter_take_buffer().
|
||||||
*
|
*
|
||||||
* Returns #NULL if @size bytes are not available.
|
* Returns #NULL if @size bytes are not available.
|
||||||
*
|
*
|
||||||
|
@ -232,8 +235,10 @@ gst_adapter_peek (GstAdapter * adapter, guint size)
|
||||||
g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
|
g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
|
||||||
g_return_val_if_fail (size > 0, NULL);
|
g_return_val_if_fail (size > 0, NULL);
|
||||||
|
|
||||||
/* we don't have enough data, return NULL */
|
/* we don't have enough data, return NULL. This is unlikely
|
||||||
if (size > adapter->size)
|
* as one usually does a _available() first instead of peeking a
|
||||||
|
* random size. */
|
||||||
|
if (G_UNLIKELY (size > adapter->size))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* we have enough assembled data, return it */
|
/* we have enough assembled data, return it */
|
||||||
|
@ -256,6 +261,7 @@ gst_adapter_peek (GstAdapter * adapter, guint size)
|
||||||
copied = GST_BUFFER_SIZE (cur) - adapter->skip;
|
copied = GST_BUFFER_SIZE (cur) - adapter->skip;
|
||||||
memcpy (adapter->assembled_data, GST_BUFFER_DATA (cur) + adapter->skip,
|
memcpy (adapter->assembled_data, GST_BUFFER_DATA (cur) + adapter->skip,
|
||||||
copied);
|
copied);
|
||||||
|
|
||||||
cur_list = g_slist_next (adapter->buflist);
|
cur_list = g_slist_next (adapter->buflist);
|
||||||
while (copied < size) {
|
while (copied < size) {
|
||||||
g_assert (cur_list);
|
g_assert (cur_list);
|
||||||
|
@ -330,7 +336,6 @@ gst_adapter_take (GstAdapter * adapter, guint nbytes)
|
||||||
GST_LOG_OBJECT (adapter, "taking %u bytes", nbytes);
|
GST_LOG_OBJECT (adapter, "taking %u bytes", nbytes);
|
||||||
|
|
||||||
cdata = gst_adapter_peek (adapter, nbytes);
|
cdata = gst_adapter_peek (adapter, nbytes);
|
||||||
|
|
||||||
if (!cdata)
|
if (!cdata)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -342,6 +347,48 @@ gst_adapter_take (GstAdapter * adapter, guint nbytes)
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_adapter_take_buffer:
|
||||||
|
* @adapter: a #GstAdapter
|
||||||
|
* @nbytes: the number of bytes to take
|
||||||
|
*
|
||||||
|
* Returns a #GstBuffer containing the first @nbytes bytes of the
|
||||||
|
* @adapter. The returned bytes will be flushed from the adapter.
|
||||||
|
* This function is potentially more performant that gst_adapter_take()
|
||||||
|
* since it can reuse the memory in the pushed buffer by subbuffering
|
||||||
|
* or merging.
|
||||||
|
*
|
||||||
|
* Caller owns returned value. gst_buffer_unref() after usage.
|
||||||
|
*
|
||||||
|
* Since: 0.10.6
|
||||||
|
*
|
||||||
|
* Returns: a #GstBuffer containing the first @nbytes of the adapter,
|
||||||
|
* or #NULL if @nbytes bytes are not available
|
||||||
|
*/
|
||||||
|
GstBuffer *
|
||||||
|
gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
|
||||||
|
{
|
||||||
|
GstBuffer *buffer;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
|
||||||
|
g_return_val_if_fail (nbytes > 0, NULL);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (adapter, "taking buffer of %u bytes", nbytes);
|
||||||
|
|
||||||
|
/* FIXME, optimize me */
|
||||||
|
data = gst_adapter_take (adapter, nbytes);
|
||||||
|
if (data == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buffer = gst_buffer_new ();
|
||||||
|
GST_BUFFER_DATA (buffer) = data;
|
||||||
|
GST_BUFFER_MALLOCDATA (buffer) = data;
|
||||||
|
GST_BUFFER_SIZE (buffer) = nbytes;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_adapter_available:
|
* gst_adapter_available:
|
||||||
* @adapter: a #GstAdapter
|
* @adapter: a #GstAdapter
|
||||||
|
@ -374,10 +421,17 @@ gst_adapter_available_fast (GstAdapter * adapter)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
|
g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
|
||||||
|
|
||||||
|
/* no buffers, we have no data */
|
||||||
if (!adapter->buflist)
|
if (!adapter->buflist)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* some stuff we already assembled */
|
||||||
if (adapter->assembled_len)
|
if (adapter->assembled_len)
|
||||||
return adapter->assembled_len;
|
return adapter->assembled_len;
|
||||||
|
|
||||||
|
/* we cannot have skipped more than the first buffer */
|
||||||
g_assert (GST_BUFFER_SIZE (adapter->buflist->data) > adapter->skip);
|
g_assert (GST_BUFFER_SIZE (adapter->buflist->data) > adapter->skip);
|
||||||
|
|
||||||
|
/* we can quickly get the data of the first buffer */
|
||||||
return GST_BUFFER_SIZE (adapter->buflist->data) - adapter->skip;
|
return GST_BUFFER_SIZE (adapter->buflist->data) - adapter->skip;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,8 @@ void gst_adapter_clear (GstAdapter *adapter);
|
||||||
void gst_adapter_push (GstAdapter *adapter, GstBuffer* buf);
|
void gst_adapter_push (GstAdapter *adapter, GstBuffer* buf);
|
||||||
const guint8 * gst_adapter_peek (GstAdapter *adapter, guint size);
|
const guint8 * gst_adapter_peek (GstAdapter *adapter, guint size);
|
||||||
void gst_adapter_flush (GstAdapter *adapter, guint flush);
|
void gst_adapter_flush (GstAdapter *adapter, guint flush);
|
||||||
guint8* gst_adapter_take (GstAdapter * adapter, guint nbytes);
|
guint8* gst_adapter_take (GstAdapter *adapter, guint nbytes);
|
||||||
|
GstBuffer* gst_adapter_take_buffer (GstAdapter *adapter, guint nbytes);
|
||||||
guint gst_adapter_available (GstAdapter *adapter);
|
guint gst_adapter_available (GstAdapter *adapter);
|
||||||
guint gst_adapter_available_fast (GstAdapter *adapter);
|
guint gst_adapter_available_fast (GstAdapter *adapter);
|
||||||
GType gst_adapter_get_type (void);
|
GType gst_adapter_get_type (void);
|
||||||
|
|
|
@ -78,6 +78,7 @@ check_PROGRAMS = \
|
||||||
$(REGISTRY_CHECKS) \
|
$(REGISTRY_CHECKS) \
|
||||||
libs/libsabi \
|
libs/libsabi \
|
||||||
libs/gdp \
|
libs/gdp \
|
||||||
|
libs/adapter \
|
||||||
libs/gstnetclientclock \
|
libs/gstnetclientclock \
|
||||||
libs/gstnettimeprovider
|
libs/gstnettimeprovider
|
||||||
|
|
||||||
|
@ -104,6 +105,9 @@ elements_fdsrc_CFLAGS=$(GST_OBJ_CFLAGS) $(CHECK_CFLAGS) -DTESTFILE=\"$(top_srcdi
|
||||||
libs_basesrc_LDADD = \
|
libs_basesrc_LDADD = \
|
||||||
$(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \
|
$(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \
|
||||||
$(LDADD)
|
$(LDADD)
|
||||||
|
libs_adapter_LDADD = \
|
||||||
|
$(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \
|
||||||
|
$(LDADD)
|
||||||
libs_controller_LDADD = \
|
libs_controller_LDADD = \
|
||||||
$(top_builddir)/libs/gst/controller/libgstcontroller-@GST_MAJORMINOR@.la \
|
$(top_builddir)/libs/gst/controller/libgstcontroller-@GST_MAJORMINOR@.la \
|
||||||
$(LDADD)
|
$(LDADD)
|
||||||
|
|
206
tests/check/libs/adapter.c
Normal file
206
tests/check/libs/adapter.c
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
/* GStreamer
|
||||||
|
*
|
||||||
|
* unit test for adapter
|
||||||
|
*
|
||||||
|
* Copyright (C) <2005> Wim Taymans <wim at fluendo dot com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/check/gstcheck.h>
|
||||||
|
|
||||||
|
#include <gst/base/gstadapter.h>
|
||||||
|
|
||||||
|
/* does some implementation dependent checking that should
|
||||||
|
* also be optimal
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start peeking on an adapter with 1 buffer pushed.
|
||||||
|
*/
|
||||||
|
GST_START_TEST (test_peek1)
|
||||||
|
{
|
||||||
|
GstAdapter *adapter;
|
||||||
|
GstBuffer *buffer;
|
||||||
|
guint avail;
|
||||||
|
const guint8 *bufdata, *data1, *data2;
|
||||||
|
|
||||||
|
adapter = gst_adapter_new ();
|
||||||
|
fail_if (adapter == NULL);
|
||||||
|
|
||||||
|
/* push single buffer in adapter */
|
||||||
|
buffer = gst_buffer_new_and_alloc (512);
|
||||||
|
bufdata = GST_BUFFER_DATA (buffer);
|
||||||
|
|
||||||
|
fail_if (buffer == NULL);
|
||||||
|
gst_adapter_push (adapter, buffer);
|
||||||
|
|
||||||
|
/* available and available_fast should return the size of the
|
||||||
|
* buffer */
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_if (avail != 512);
|
||||||
|
avail = gst_adapter_available_fast (adapter);
|
||||||
|
fail_if (avail != 512);
|
||||||
|
|
||||||
|
/* should g_critical with NULL as result */
|
||||||
|
ASSERT_CRITICAL (data1 = gst_adapter_peek (adapter, 0));
|
||||||
|
fail_if (data1 != NULL);
|
||||||
|
|
||||||
|
/* should return NULL as result */
|
||||||
|
data1 = gst_adapter_peek (adapter, 513);
|
||||||
|
fail_if (data1 != NULL);
|
||||||
|
|
||||||
|
/* this should work */
|
||||||
|
data1 = gst_adapter_peek (adapter, 512);
|
||||||
|
fail_if (data1 == NULL);
|
||||||
|
/* it should point to the buffer data as well */
|
||||||
|
fail_if (data1 != bufdata);
|
||||||
|
data2 = gst_adapter_peek (adapter, 512);
|
||||||
|
fail_if (data2 == NULL);
|
||||||
|
/* second peek should return the same pointer */
|
||||||
|
fail_if (data2 != data1);
|
||||||
|
|
||||||
|
/* this should fail since we don't have that many bytes */
|
||||||
|
ASSERT_CRITICAL (gst_adapter_flush (adapter, 513));
|
||||||
|
|
||||||
|
/* this should work fine */
|
||||||
|
gst_adapter_flush (adapter, 10);
|
||||||
|
|
||||||
|
/* see if we have 10 bytes less available */
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_if (avail != 502);
|
||||||
|
avail = gst_adapter_available_fast (adapter);
|
||||||
|
fail_if (avail != 502);
|
||||||
|
|
||||||
|
/* should return NULL as result */
|
||||||
|
data2 = gst_adapter_peek (adapter, 503);
|
||||||
|
fail_if (data2 != NULL);
|
||||||
|
|
||||||
|
/* should work fine */
|
||||||
|
data2 = gst_adapter_peek (adapter, 502);
|
||||||
|
fail_if (data2 == NULL);
|
||||||
|
/* peek should return the same old pointer + 10 */
|
||||||
|
fail_if (data2 != data1 + 10);
|
||||||
|
fail_if (data2 != bufdata + 10);
|
||||||
|
|
||||||
|
/* flush some more */
|
||||||
|
gst_adapter_flush (adapter, 500);
|
||||||
|
|
||||||
|
/* see if we have 2 bytes available */
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_if (avail != 2);
|
||||||
|
avail = gst_adapter_available_fast (adapter);
|
||||||
|
fail_if (avail != 2);
|
||||||
|
|
||||||
|
data2 = gst_adapter_peek (adapter, 2);
|
||||||
|
fail_if (data2 == NULL);
|
||||||
|
fail_if (data2 != data1 + 510);
|
||||||
|
fail_if (data2 != bufdata + 510);
|
||||||
|
|
||||||
|
/* flush some more */
|
||||||
|
gst_adapter_flush (adapter, 2);
|
||||||
|
|
||||||
|
/* see if we have 0 bytes available */
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_if (avail != 0);
|
||||||
|
avail = gst_adapter_available_fast (adapter);
|
||||||
|
fail_if (avail != 0);
|
||||||
|
|
||||||
|
/* silly clear just for fun */
|
||||||
|
gst_adapter_clear (adapter);
|
||||||
|
|
||||||
|
g_object_unref (adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* Start peeking on an adapter with 2 non-mergeable buffers
|
||||||
|
* pushed.
|
||||||
|
*/
|
||||||
|
GST_START_TEST (test_peek2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* Start peeking on an adapter with 2 mergeable buffers
|
||||||
|
* pushed.
|
||||||
|
*/
|
||||||
|
GST_START_TEST (test_peek3)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* take data from an adapter with 1 buffer pushed.
|
||||||
|
*/
|
||||||
|
GST_START_TEST (test_take1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* take data from an adapter with 2 non-mergeable buffers
|
||||||
|
* pushed.
|
||||||
|
*/
|
||||||
|
GST_START_TEST (test_take2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
/* take data from an adapter with 2 mergeable buffers
|
||||||
|
* pushed.
|
||||||
|
*/
|
||||||
|
GST_START_TEST (test_take3)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
Suite *
|
||||||
|
gst_adapter_suite (void)
|
||||||
|
{
|
||||||
|
Suite *s = suite_create ("adapter");
|
||||||
|
TCase *tc_chain = tcase_create ("general");
|
||||||
|
|
||||||
|
suite_add_tcase (s, tc_chain);
|
||||||
|
tcase_add_test (tc_chain, test_peek1);
|
||||||
|
tcase_add_test (tc_chain, test_peek2);
|
||||||
|
tcase_add_test (tc_chain, test_peek3);
|
||||||
|
tcase_add_test (tc_chain, test_take1);
|
||||||
|
tcase_add_test (tc_chain, test_take2);
|
||||||
|
tcase_add_test (tc_chain, test_take3);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int nf;
|
||||||
|
|
||||||
|
Suite *s = gst_adapter_suite ();
|
||||||
|
SRunner *sr = srunner_create (s);
|
||||||
|
|
||||||
|
gst_check_init (&argc, &argv);
|
||||||
|
|
||||||
|
srunner_run_all (sr, CK_NORMAL);
|
||||||
|
nf = srunner_ntests_failed (sr);
|
||||||
|
srunner_free (sr);
|
||||||
|
|
||||||
|
return nf;
|
||||||
|
}
|
Loading…
Reference in a new issue