buffer: make function to find memory in a buffer

Make a function to find the memory blocks for a region in a buffer.
This commit is contained in:
Wim Taymans 2012-04-01 11:42:52 +02:00
parent 7f628113e4
commit 0e9241cfc6
5 changed files with 162 additions and 0 deletions

View file

@ -196,6 +196,7 @@ gst_buffer_insert_memory
gst_buffer_replace_memory_range
gst_buffer_get_memory_range
gst_buffer_remove_memory_range
gst_buffer_find_memory
gst_buffer_prepend_memory
gst_buffer_append_memory

View file

@ -898,6 +898,79 @@ gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, gint length)
GST_BUFFER_MEM_LEN (buffer) = len - length;
}
/**
* gst_buffer_find_memory:
* @buffer: a #GstBuffer.
* @offset: an offset
* @size: a size
* @idx: (out): pointer to index
* @length: (out): pointer to length
* @skip: (out): pointer to skip
*
* Find the memory blocks that span @size bytes starting from @offset
* in @buffer.
*
* When this function returns %TRUE, @idx will contain the index of the first
* memory bock where the byte for @offset can be found and @length contains the
* number of memory blocks containing the @size remaining bytes. @skip contains
* the number of bytes to skip in the memory bock at @idx to get to the byte
* for @offset.
*
* @size can be -1 to get all the memory blocks after @idx.
*
* Returns: %TRUE when @size bytes starting from @offset could be found in
* @buffer and @idx, @length and @skip will be filled.
*/
gboolean
gst_buffer_find_memory (GstBuffer * buffer, gsize offset, gsize size,
guint * idx, guint * length, gsize * skip)
{
guint i, len, found;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
g_return_val_if_fail (idx != NULL, FALSE);
g_return_val_if_fail (length != NULL, FALSE);
g_return_val_if_fail (skip != NULL, FALSE);
len = GST_BUFFER_MEM_LEN (buffer);
found = 0;
for (i = 0; i < len; i++) {
GstMemory *mem;
gsize s;
mem = GST_BUFFER_MEM_PTR (buffer, i);
s = gst_memory_get_sizes (mem, NULL, NULL);
if (s <= offset) {
/* block before offset, or empty block, skip */
offset -= s;
} else {
/* block after offset */
if (found == 0) {
/* first block, remember index and offset */
*idx = i;
*skip = offset;
if (size == -1) {
/* return remaining blocks */
*length = len - i;
return TRUE;
}
s -= offset;
offset = 0;
}
/* count the amount of found bytes */
found += s;
if (found >= size) {
/* we have enough bytes */
*length = i - *idx + 1;
return TRUE;
}
}
}
return FALSE;
}
/**
* gst_buffer_get_sizes:
* @buffer: a #GstBuffer.

View file

@ -289,6 +289,9 @@ void gst_buffer_remove_memory_range (GstBuffer *buffer, guint idx, gint
#define gst_buffer_remove_memory(b,i) gst_buffer_remove_memory_range ((b), (i), 1)
#define gst_buffer_remove_all_memory(b) gst_buffer_remove_memory_range ((b), 0, -1)
gboolean gst_buffer_find_memory (GstBuffer *buffer, gsize offset, gsize size,
guint *idx, guint *length, gsize *skip);
gsize gst_buffer_fill (GstBuffer *buffer, gsize offset,
gconstpointer src, gsize size);
gsize gst_buffer_extract (GstBuffer *buffer, gsize offset,

View file

@ -603,6 +603,89 @@ GST_START_TEST (test_map)
GST_END_TEST;
GST_START_TEST (test_find)
{
GstBuffer *buf;
gsize maxalloc;
gsize size, offset;
guint idx, length;
buf = gst_buffer_new ();
gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 0, NULL));
gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 10, NULL));
gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 15, NULL));
gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 0, NULL));
size = gst_buffer_get_sizes (buf, &offset, &maxalloc);
fail_unless (size == 25);
fail_unless (offset >= 0);
fail_unless (maxalloc >= 25);
fail_unless (gst_buffer_n_memory (buf) == 4);
fail_unless (gst_buffer_find_memory (buf, 0, 5, &idx, &length, &offset));
fail_unless (idx == 1);
fail_unless (length == 1);
fail_unless (offset == 0);
fail_unless (gst_buffer_find_memory (buf, 0, 10, &idx, &length, &offset));
fail_unless (idx == 1);
fail_unless (length == 1);
fail_unless (offset == 0);
fail_unless (gst_buffer_find_memory (buf, 5, 4, &idx, &length, &offset));
fail_unless (idx == 1);
fail_unless (length == 1);
fail_unless (offset == 5);
fail_unless (gst_buffer_find_memory (buf, 5, 5, &idx, &length, &offset));
fail_unless (idx == 1);
fail_unless (length == 1);
fail_unless (offset == 5);
fail_unless (gst_buffer_find_memory (buf, 5, 6, &idx, &length, &offset));
fail_unless (idx == 1);
fail_unless (length == 2);
fail_unless (offset == 5);
fail_unless (gst_buffer_find_memory (buf, 10, 6, &idx, &length, &offset));
fail_unless (idx == 2);
fail_unless (length == 1);
fail_unless (offset == 0);
fail_unless (gst_buffer_find_memory (buf, 10, 15, &idx, &length, &offset));
fail_unless (idx == 2);
fail_unless (length == 1);
fail_unless (offset == 0);
fail_unless (gst_buffer_find_memory (buf, 11, 14, &idx, &length, &offset));
fail_unless (idx == 2);
fail_unless (length == 1);
fail_unless (offset == 1);
fail_unless (gst_buffer_find_memory (buf, 0, 25, &idx, &length, &offset));
fail_unless (idx == 1);
fail_unless (length == 2);
fail_unless (offset == 0);
fail_unless (gst_buffer_find_memory (buf, 24, 0, &idx, &length, &offset));
fail_unless (idx == 2);
fail_unless (length == 1);
fail_unless (offset == 14);
fail_if (gst_buffer_find_memory (buf, 11, 15, &idx, &length, &offset));
fail_if (gst_buffer_find_memory (buf, 0, 26, &idx, &length, &offset));
fail_if (gst_buffer_find_memory (buf, 25, 0, &idx, &length, &offset));
fail_unless (gst_buffer_find_memory (buf, 1, -1, &idx, &length, &offset));
fail_unless (idx == 1);
fail_unless (length == 3);
fail_unless (offset == 1);
gst_buffer_unref (buf);
}
GST_END_TEST;
static Suite *
gst_buffer_suite (void)
@ -621,6 +704,7 @@ gst_buffer_suite (void)
tcase_add_test (tc_chain, test_size);
tcase_add_test (tc_chain, test_resize);
tcase_add_test (tc_chain, test_map);
tcase_add_test (tc_chain, test_find);
return s;
}

View file

@ -96,6 +96,7 @@ EXPORTS
gst_buffer_copy_region
gst_buffer_extract
gst_buffer_fill
gst_buffer_find_memory
gst_buffer_flags_get_type
gst_buffer_foreach_meta
gst_buffer_get_memory_range