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>
|
||||
|
||||
* docs/design/part-overview.txt:
|
||||
|
|
|
@ -112,6 +112,7 @@ gst_adapter_flush
|
|||
gst_adapter_available
|
||||
gst_adapter_available_fast
|
||||
gst_adapter_take
|
||||
gst_adapter_take_buffer
|
||||
<SUBSECTION Standard>
|
||||
GstAdapterClass
|
||||
GST_ADAPTER
|
||||
|
|
|
@ -199,6 +199,8 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
|
|||
g_return_if_fail (GST_IS_BUFFER (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);
|
||||
}
|
||||
|
||||
|
@ -216,7 +218,8 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
|
|||
* of its chain function, the buffer will have an invalid data pointer after
|
||||
* your element flushes the bytes. In that case you should use
|
||||
* 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.
|
||||
*
|
||||
|
@ -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 (size > 0, NULL);
|
||||
|
||||
/* we don't have enough data, return NULL */
|
||||
if (size > adapter->size)
|
||||
/* we don't have enough data, return NULL. This is unlikely
|
||||
* as one usually does a _available() first instead of peeking a
|
||||
* random size. */
|
||||
if (G_UNLIKELY (size > adapter->size))
|
||||
return NULL;
|
||||
|
||||
/* 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;
|
||||
memcpy (adapter->assembled_data, GST_BUFFER_DATA (cur) + adapter->skip,
|
||||
copied);
|
||||
|
||||
cur_list = g_slist_next (adapter->buflist);
|
||||
while (copied < size) {
|
||||
g_assert (cur_list);
|
||||
|
@ -330,7 +336,6 @@ gst_adapter_take (GstAdapter * adapter, guint nbytes)
|
|||
GST_LOG_OBJECT (adapter, "taking %u bytes", nbytes);
|
||||
|
||||
cdata = gst_adapter_peek (adapter, nbytes);
|
||||
|
||||
if (!cdata)
|
||||
return NULL;
|
||||
|
||||
|
@ -342,6 +347,48 @@ gst_adapter_take (GstAdapter * adapter, guint nbytes)
|
|||
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:
|
||||
* @adapter: a #GstAdapter
|
||||
|
@ -374,10 +421,17 @@ gst_adapter_available_fast (GstAdapter * adapter)
|
|||
{
|
||||
g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
|
||||
|
||||
/* no buffers, we have no data */
|
||||
if (!adapter->buflist)
|
||||
return 0;
|
||||
|
||||
/* some stuff we already assembled */
|
||||
if (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);
|
||||
|
||||
/* we can quickly get the data of the first buffer */
|
||||
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);
|
||||
const guint8 * gst_adapter_peek (GstAdapter *adapter, guint size);
|
||||
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_fast (GstAdapter *adapter);
|
||||
GType gst_adapter_get_type (void);
|
||||
|
|
|
@ -78,6 +78,7 @@ check_PROGRAMS = \
|
|||
$(REGISTRY_CHECKS) \
|
||||
libs/libsabi \
|
||||
libs/gdp \
|
||||
libs/adapter \
|
||||
libs/gstnetclientclock \
|
||||
libs/gstnettimeprovider
|
||||
|
||||
|
@ -104,6 +105,9 @@ elements_fdsrc_CFLAGS=$(GST_OBJ_CFLAGS) $(CHECK_CFLAGS) -DTESTFILE=\"$(top_srcdi
|
|||
libs_basesrc_LDADD = \
|
||||
$(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \
|
||||
$(LDADD)
|
||||
libs_adapter_LDADD = \
|
||||
$(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \
|
||||
$(LDADD)
|
||||
libs_controller_LDADD = \
|
||||
$(top_builddir)/libs/gst/controller/libgstcontroller-@GST_MAJORMINOR@.la \
|
||||
$(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