mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-04 23:30:05 +00:00
1 Add option GST_BUFFER_WHERE (off by default) to track the file:line info where each buffer is created. This is use...
Original commit message from CVS: 1 Add option GST_BUFFER_WHERE (off by default) to track the file:line info where each buffer is created. This is useful for tracking buffer memory leaks. 2 Removed gst_buffer_ref_by_count. 3 Merged the GstBufferCopyFunc fix from HEAD.
This commit is contained in:
parent
c1051d5087
commit
4f81b9a5da
3 changed files with 157 additions and 60 deletions
126
gst/gstbuffer.c
126
gst/gstbuffer.c
|
@ -32,6 +32,13 @@ GType _gst_buffer_type;
|
|||
static GMemChunk *_gst_buffer_chunk;
|
||||
static GMutex *_gst_buffer_chunk_lock;
|
||||
|
||||
#ifdef GST_BUFFER_WHERE
|
||||
static GSList *_debug_live = 0;
|
||||
# define GST_BUFFERS_COUNT (g_slist_length(_debug_live))
|
||||
#else
|
||||
# define GST_BUFFERS_COUNT 1
|
||||
#endif
|
||||
|
||||
void
|
||||
_gst_buffer_initialize (void)
|
||||
{
|
||||
|
@ -67,12 +74,15 @@ _gst_buffer_initialize (void)
|
|||
* Returns: new buffer
|
||||
*/
|
||||
GstBuffer*
|
||||
gst_buffer_new (void)
|
||||
gst_buffer_new_loc (GST_WHERE)
|
||||
{
|
||||
GstBuffer *buffer;
|
||||
|
||||
g_mutex_lock (_gst_buffer_chunk_lock);
|
||||
buffer = g_mem_chunk_alloc (_gst_buffer_chunk);
|
||||
#ifdef GST_BUFFER_WHERE
|
||||
_debug_live = g_slist_prepend (_debug_live, buffer);
|
||||
#endif
|
||||
g_mutex_unlock (_gst_buffer_chunk_lock);
|
||||
GST_INFO (GST_CAT_BUFFER,"creating new buffer %p",buffer);
|
||||
|
||||
|
@ -96,6 +106,11 @@ gst_buffer_new (void)
|
|||
buffer->free = NULL;
|
||||
buffer->copy = NULL;
|
||||
|
||||
#ifdef GST_BUFFER_WHERE
|
||||
buffer->file = where_file;
|
||||
buffer->line = where_line;
|
||||
#endif
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -108,18 +123,21 @@ gst_buffer_new (void)
|
|||
* Returns: new buffer
|
||||
*/
|
||||
GstBuffer*
|
||||
gst_buffer_new_from_pool (GstBufferPool *pool, guint64 location, gint size)
|
||||
gst_buffer_new_from_pool (GstBufferPool *pool, guint32 offset, guint32 size)
|
||||
{
|
||||
GstBuffer *buffer;
|
||||
|
||||
g_return_val_if_fail (pool != NULL, NULL);
|
||||
g_return_val_if_fail (pool->buffer_new != NULL, NULL);
|
||||
|
||||
buffer = pool->buffer_new (pool, location, size, pool->user_data);
|
||||
buffer = pool->buffer_new (pool, offset, size, pool->user_data);
|
||||
buffer->pool = pool;
|
||||
buffer->free = pool->buffer_free;
|
||||
buffer->copy = pool->buffer_copy;
|
||||
|
||||
GST_INFO (GST_CAT_BUFFER,"creating new buffer %p from pool %p (size %x, offset %x)",
|
||||
buffer, pool, size, offset);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -134,9 +152,10 @@ gst_buffer_new_from_pool (GstBufferPool *pool, guint64 location, gint size)
|
|||
* Returns: new buffer
|
||||
*/
|
||||
GstBuffer*
|
||||
gst_buffer_create_sub (GstBuffer *parent,
|
||||
guint32 offset,
|
||||
guint32 size)
|
||||
gst_buffer_create_sub_loc (GST_WHERE_
|
||||
GstBuffer *parent,
|
||||
guint32 offset,
|
||||
guint32 size)
|
||||
{
|
||||
GstBuffer *buffer;
|
||||
|
||||
|
@ -146,6 +165,9 @@ gst_buffer_create_sub (GstBuffer *parent,
|
|||
|
||||
g_mutex_lock (_gst_buffer_chunk_lock);
|
||||
buffer = g_mem_chunk_alloc (_gst_buffer_chunk);
|
||||
#ifdef GST_BUFFER_WHERE
|
||||
_debug_live = g_slist_prepend (_debug_live, buffer);
|
||||
#endif
|
||||
g_mutex_unlock (_gst_buffer_chunk_lock);
|
||||
GST_INFO (GST_CAT_BUFFER,"creating new subbuffer %p from parent %p (size %u, offset %u)",
|
||||
buffer, parent, size, offset);
|
||||
|
@ -184,7 +206,12 @@ gst_buffer_create_sub (GstBuffer *parent,
|
|||
gst_buffer_ref (parent);
|
||||
|
||||
buffer->pool = NULL;
|
||||
// return the new subbuffer
|
||||
|
||||
#ifdef GST_BUFFER_WHERE
|
||||
buffer->file = where_file;
|
||||
buffer->line = where_line;
|
||||
#endif
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -201,8 +228,9 @@ gst_buffer_create_sub (GstBuffer *parent,
|
|||
* Returns: new buffer
|
||||
*/
|
||||
GstBuffer*
|
||||
gst_buffer_append (GstBuffer *buffer,
|
||||
GstBuffer *append)
|
||||
gst_buffer_append_loc (GST_WHERE_
|
||||
GstBuffer *buffer,
|
||||
GstBuffer *append)
|
||||
{
|
||||
guint size;
|
||||
GstBuffer *newbuf;
|
||||
|
@ -226,7 +254,7 @@ gst_buffer_append (GstBuffer *buffer,
|
|||
}
|
||||
// the buffer is used, create a new one
|
||||
else {
|
||||
newbuf = gst_buffer_new ();
|
||||
newbuf = gst_buffer_new_loc (GST_WHERE_VARS);
|
||||
newbuf->size = buffer->size+append->size;
|
||||
newbuf->data = g_malloc (newbuf->size);
|
||||
memcpy (newbuf->data, buffer->data, buffer->size);
|
||||
|
@ -250,7 +278,10 @@ gst_buffer_destroy (GstBuffer *buffer)
|
|||
|
||||
g_return_if_fail (buffer != NULL);
|
||||
|
||||
GST_INFO (GST_CAT_BUFFER,"freeing %sbuffer %p", (buffer->parent?"sub":""),buffer);
|
||||
GST_INFO (GST_CAT_BUFFER, "freeing %sbuffer %p (%ld buffers remain)",
|
||||
(buffer->parent?"sub":""),
|
||||
buffer,
|
||||
GST_BUFFERS_COUNT - 1);
|
||||
|
||||
// free the data only if there is some, DONTFREE isn't set, and not sub
|
||||
if (GST_BUFFER_DATA (buffer) &&
|
||||
|
@ -271,12 +302,33 @@ gst_buffer_destroy (GstBuffer *buffer)
|
|||
g_mutex_free (buffer->lock);
|
||||
//g_print("freed mutex\n");
|
||||
|
||||
#ifdef GST_DEBUG_ENABLED
|
||||
// make it hard to reuse by mistake
|
||||
memset (buffer, ~0, sizeof (GstBuffer));
|
||||
#endif
|
||||
|
||||
// remove it entirely from memory
|
||||
g_mutex_lock (_gst_buffer_chunk_lock);
|
||||
g_mem_chunk_free (_gst_buffer_chunk,buffer);
|
||||
#ifdef GST_BUFFER_WHERE
|
||||
_debug_live = g_slist_delete_link (_debug_live,
|
||||
g_slist_find (_debug_live, buffer));
|
||||
#endif
|
||||
g_mutex_unlock (_gst_buffer_chunk_lock);
|
||||
}
|
||||
|
||||
#ifdef GST_BUFFER_WHERE
|
||||
void gst_buffer_print_live ()
|
||||
{
|
||||
GSList *elem;
|
||||
|
||||
for (elem = _debug_live; elem; elem = elem->next) {
|
||||
GstBuffer *buf = elem->data;
|
||||
g_print ("buffer %p created %s:%d\n", buf, buf->file, buf->line);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* gst_buffer_ref:
|
||||
* @buffer: the GstBuffer to reference
|
||||
|
@ -288,7 +340,7 @@ gst_buffer_ref (GstBuffer *buffer)
|
|||
{
|
||||
g_return_if_fail (buffer != NULL);
|
||||
|
||||
GST_DEBUG (0,"referencing buffer %p\n", buffer);
|
||||
GST_INFO (GST_CAT_BUFFER, "ref buffer %p\n", buffer);
|
||||
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
//g_return_if_fail(atomic_read(&(buffer->refcount)) > 0);
|
||||
|
@ -301,30 +353,6 @@ gst_buffer_ref (GstBuffer *buffer)
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_buffer_ref_by_count:
|
||||
* @buffer: the GstBuffer to reference
|
||||
* @count: a number
|
||||
*
|
||||
* Increment the refcount of this buffer by the given number.
|
||||
*/
|
||||
void
|
||||
gst_buffer_ref_by_count (GstBuffer *buffer, int count)
|
||||
{
|
||||
g_return_if_fail (buffer != NULL);
|
||||
g_return_if_fail (count > 0);
|
||||
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
g_return_if_fail (atomic_read (&(buffer->refcount)) > 0);
|
||||
atomic_add (count, &(buffer->refcount));
|
||||
#else
|
||||
g_return_if_fail (buffer->refcount > 0);
|
||||
GST_BUFFER_LOCK (buffer);
|
||||
buffer->refcount += count;
|
||||
GST_BUFFER_UNLOCK (buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_buffer_unref:
|
||||
* @buffer: the GstBuffer to unref
|
||||
|
@ -339,7 +367,7 @@ gst_buffer_unref (GstBuffer *buffer)
|
|||
|
||||
g_return_if_fail (buffer != NULL);
|
||||
|
||||
GST_DEBUG (0,"unreferencing buffer %p\n", buffer);
|
||||
GST_INFO (GST_CAT_BUFFER, "unref buffer %p\n", buffer);
|
||||
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
g_return_if_fail (atomic_read (&(buffer->refcount)) > 0);
|
||||
|
@ -367,17 +395,17 @@ gst_buffer_unref (GstBuffer *buffer)
|
|||
* Returns: new buffer
|
||||
*/
|
||||
GstBuffer *
|
||||
gst_buffer_copy (GstBuffer *buffer)
|
||||
gst_buffer_copy_loc (GST_WHERE_ GstBuffer *buffer)
|
||||
{
|
||||
GstBuffer *newbuf;
|
||||
|
||||
// allocate a new buffer
|
||||
newbuf = gst_buffer_new();
|
||||
|
||||
// if a copy function exists, use it, else copy the bytes
|
||||
if (buffer->copy != NULL) {
|
||||
(buffer->copy)(buffer,newbuf);
|
||||
newbuf = (buffer->copy)(buffer);
|
||||
} else {
|
||||
// allocate a new buffer
|
||||
newbuf = gst_buffer_new();
|
||||
|
||||
// copy the absolute size
|
||||
newbuf->size = buffer->size;
|
||||
// allocate space for the copy
|
||||
|
@ -436,7 +464,8 @@ gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2)
|
|||
*/
|
||||
// FIXME need to think about CoW and such...
|
||||
GstBuffer *
|
||||
gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
|
||||
gst_buffer_span_loc (GST_WHERE_
|
||||
GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
|
||||
{
|
||||
GstBuffer *newbuf;
|
||||
|
||||
|
@ -453,12 +482,13 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
|
|||
// ((buf1->data + buf1->size) == buf2->data)) {
|
||||
if (gst_buffer_is_span_fast(buf1,buf2)) {
|
||||
// we simply create a subbuffer of the common parent
|
||||
newbuf = gst_buffer_create_sub(buf1->parent, buf1->data - (buf1->parent->data) + offset, len);
|
||||
newbuf = gst_buffer_create_sub_loc(GST_WHERE_VARS_
|
||||
buf1->parent, buf1->data - (buf1->parent->data) + offset, len);
|
||||
}
|
||||
else {
|
||||
g_print ("slow path taken in buffer_span\n");
|
||||
// otherwise we simply have to brute-force copy the buffers
|
||||
newbuf = gst_buffer_new();
|
||||
newbuf = gst_buffer_new_loc (GST_WHERE_VARS);
|
||||
|
||||
// put in new size
|
||||
newbuf->size = len;
|
||||
|
@ -496,8 +526,10 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
|
|||
* Returns: new buffer that's the concatenation of the source buffers
|
||||
*/
|
||||
GstBuffer *
|
||||
gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2)
|
||||
gst_buffer_merge_loc (GST_WHERE_
|
||||
GstBuffer *buf1, GstBuffer *buf2)
|
||||
{
|
||||
// we're just a specific case of the more general gst_buffer_span()
|
||||
return gst_buffer_span(buf1, 0, buf2, buf1->size + buf2->size);
|
||||
return gst_buffer_span_loc (GST_WHERE_VARS_
|
||||
buf1, 0, buf2, buf1->size + buf2->size);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,13 @@
|
|||
#ifndef __GST_BUFFER_H__
|
||||
#define __GST_BUFFER_H__
|
||||
|
||||
//
|
||||
// Define this to add file:line info to each GstBuffer showing
|
||||
// the location in the source code where the buffer was created.
|
||||
//
|
||||
// #define GST_BUFFER_WHERE
|
||||
//
|
||||
|
||||
#include <gst/gstdata.h>
|
||||
#include <gst/gstobject.h>
|
||||
|
||||
|
@ -89,8 +96,8 @@ typedef enum {
|
|||
typedef struct _GstBuffer GstBuffer;
|
||||
|
||||
|
||||
typedef void (*GstBufferFreeFunc) (GstBuffer *buf);
|
||||
typedef void (*GstBufferCopyFunc) (GstBuffer *srcbuf,GstBuffer *dstbuf);
|
||||
typedef void (*GstBufferFreeFunc) (GstBuffer *buf);
|
||||
typedef GstBuffer *(*GstBufferCopyFunc) (GstBuffer *srcbuf);
|
||||
|
||||
|
||||
#include <gst/gstbufferpool.h>
|
||||
|
@ -119,9 +126,13 @@ struct _GstBuffer {
|
|||
guint32 maxsize;
|
||||
guint32 offset;
|
||||
|
||||
#ifdef GST_BUFFER_WHERE
|
||||
const gchar *file;
|
||||
gint line;
|
||||
#endif
|
||||
|
||||
/* timestamp */
|
||||
gint64 timestamp;
|
||||
/* max age */
|
||||
gint64 maxage;
|
||||
|
||||
/* subbuffer support, who's my parent? */
|
||||
|
@ -136,30 +147,76 @@ struct _GstBuffer {
|
|||
GstBufferCopyFunc copy; // copy the data from one buffer to another
|
||||
};
|
||||
|
||||
#ifdef GST_BUFFER_WHERE
|
||||
|
||||
# define GST_WHERE const gchar *where_file, gint where_line
|
||||
# define GST_WHERE_ GST_WHERE,
|
||||
# define GST_WHERE_VARS where_file, where_line
|
||||
# define GST_WHERE_VARS_ where_file, where_line,
|
||||
|
||||
# define gst_buffer_new() \
|
||||
gst_buffer_new_loc(__FILE__, __LINE__)
|
||||
# define gst_buffer_create_sub(parent, offset, size) \
|
||||
gst_buffer_create_sub_loc(__FILE__, __LINE__, parent, offset, size)
|
||||
# define gst_buffer_copy(buffer) \
|
||||
gst_buffer_copy_loc(__FILE__, __LINE__, buffer)
|
||||
# define gst_buffer_merge(buf1, buf2) \
|
||||
gst_buffer_merge_loc(__FILE__, __LINE__, buf1, buf2)
|
||||
# define gst_buffer_span(buf1, offset, buf2, len) \
|
||||
gst_buffer_span_loc(__FILE__, __LINE__, buf1, offset, buf2, len)
|
||||
# define gst_buffer_append(buf, buf2) \
|
||||
gst_buffer_append_loc(__FILE__, __LINE__, buf, buf2)
|
||||
|
||||
#else /* GST_BUFFER_WHERE */
|
||||
|
||||
# define GST_WHERE
|
||||
# define GST_WHERE_
|
||||
# define GST_WHERE_VARS
|
||||
# define GST_WHERE_VARS_
|
||||
|
||||
# define gst_buffer_new() \
|
||||
gst_buffer_new_loc()
|
||||
# define gst_buffer_create_sub(parent, offset, size) \
|
||||
gst_buffer_create_sub_loc(parent, offset, size)
|
||||
# define gst_buffer_copy(buffer) \
|
||||
gst_buffer_copy_loc(buffer)
|
||||
# define gst_buffer_merge(buf1, buf2) \
|
||||
gst_buffer_merge_loc(buf1, buf2)
|
||||
# define gst_buffer_span(buf1, offset, buf2, len) \
|
||||
gst_buffer_span_loc(buf1, offset, buf2, len)
|
||||
# define gst_buffer_append(buf, buf2) \
|
||||
gst_buffer_append_loc(buf, buf2)
|
||||
|
||||
#endif /* GST_BUFFER_WHERE */
|
||||
|
||||
/* initialisation */
|
||||
void _gst_buffer_initialize (void);
|
||||
/* creating a new buffer from scratch */
|
||||
GstBuffer* gst_buffer_new (void);
|
||||
GstBuffer* gst_buffer_new_from_pool (GstBufferPool *pool, guint64 location, gint size);
|
||||
GstBuffer* gst_buffer_new_loc (GST_WHERE);
|
||||
GstBuffer* gst_buffer_new_from_pool (GstBufferPool *pool, guint32 offset, guint32 size);
|
||||
|
||||
/* creating a subbuffer */
|
||||
GstBuffer* gst_buffer_create_sub (GstBuffer *parent, guint32 offset, guint32 size);
|
||||
GstBuffer* gst_buffer_create_sub_loc (GST_WHERE_
|
||||
GstBuffer *parent, guint32 offset, guint32 size);
|
||||
|
||||
/* refcounting */
|
||||
void gst_buffer_ref (GstBuffer *buffer);
|
||||
void gst_buffer_ref_by_count (GstBuffer *buffer, int count);
|
||||
void gst_buffer_unref (GstBuffer *buffer);
|
||||
|
||||
/* destroying the buffer */
|
||||
void gst_buffer_destroy (GstBuffer *buffer);
|
||||
|
||||
/* copy buffer */
|
||||
GstBuffer* gst_buffer_copy (GstBuffer *buffer);
|
||||
GstBuffer* gst_buffer_copy_loc (GST_WHERE_
|
||||
GstBuffer *buffer);
|
||||
|
||||
/* merge, span, or append two buffers, intelligently */
|
||||
GstBuffer* gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2);
|
||||
GstBuffer* gst_buffer_span (GstBuffer *buf1,guint32 offset,GstBuffer *buf2,guint32 len);
|
||||
GstBuffer* gst_buffer_append (GstBuffer *buf, GstBuffer *buf2);
|
||||
GstBuffer* gst_buffer_merge_loc (GST_WHERE_
|
||||
GstBuffer *buf1, GstBuffer *buf2);
|
||||
GstBuffer* gst_buffer_span_loc (GST_WHERE_
|
||||
GstBuffer *buf1,guint32 offset,GstBuffer *buf2,guint32 len);
|
||||
GstBuffer* gst_buffer_append_loc (GST_WHERE_
|
||||
GstBuffer *buf, GstBuffer *buf2);
|
||||
|
||||
gboolean gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2);
|
||||
|
||||
|
|
|
@ -194,7 +194,8 @@ gst_buffer_pool_set_buffer_free_function (GstBufferPool *pool,
|
|||
* @destroy: the copy function
|
||||
*
|
||||
* Sets the function that will be called when a buffer is copied.
|
||||
* You can use the default GstBuffer implementation (gst_buffer_copy) if you like.
|
||||
*
|
||||
* You may use the default GstBuffer implementation (gst_buffer_copy).
|
||||
*/
|
||||
void
|
||||
gst_buffer_pool_set_buffer_copy_function (GstBufferPool *pool,
|
||||
|
@ -273,6 +274,13 @@ gst_buffer_pool_destroy (GstBufferPool *pool)
|
|||
g_free(pool);
|
||||
}
|
||||
|
||||
//
|
||||
// This is so we don't get messed up by GST_BUFFER_WHERE.
|
||||
//
|
||||
static GstBuffer *
|
||||
_pool_gst_buffer_copy (GstBuffer *buffer)
|
||||
{ return gst_buffer_copy (buffer); }
|
||||
|
||||
/**
|
||||
* gst_buffer_pool_get_default:
|
||||
* @buffer_size: the number of bytes this buffer will store
|
||||
|
@ -313,7 +321,7 @@ gst_buffer_pool_get_default (guint buffer_size, guint pool_size)
|
|||
pool = gst_buffer_pool_new();
|
||||
gst_buffer_pool_set_buffer_new_function (pool, gst_buffer_pool_default_buffer_new);
|
||||
gst_buffer_pool_set_buffer_free_function (pool, gst_buffer_pool_default_buffer_free);
|
||||
gst_buffer_pool_set_buffer_copy_function (pool, gst_buffer_copy);
|
||||
gst_buffer_pool_set_buffer_copy_function (pool, _pool_gst_buffer_copy);
|
||||
gst_buffer_pool_set_destroy_hook (pool, gst_buffer_pool_default_destroy_hook);
|
||||
|
||||
def = g_new0 (GstBufferPoolDefault, 1);
|
||||
|
|
Loading…
Reference in a new issue