diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 55eaf92429..3ec4319ca4 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -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 diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 43a02c673c..2612419ab3 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -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. diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h index cc8200a3ea..38d6051bc2 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -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, diff --git a/tests/check/gst/gstbuffer.c b/tests/check/gst/gstbuffer.c index 5e3496c2da..1344e13bf3 100644 --- a/tests/check/gst/gstbuffer.c +++ b/tests/check/gst/gstbuffer.c @@ -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; } diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index eabffe0a26..947a949885 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -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