mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-13 21:01:14 +00:00
4c4ff33d1f
Original commit message from CVS: Trying to fix the mess that I made with the two previous commits. First commit, doing something wrong (fixing comparisons of signed and unsigned). Second commit, trying to revert the previous, but changing other things and reverting unrelated work of other people. And this third, hopefully fixes it.
223 lines
5.6 KiB
C
223 lines
5.6 KiB
C
/* GStreamer
|
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
|
*
|
|
* 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 <string.h> /* memset */
|
|
|
|
#include "gstlog.h"
|
|
#include "gstutils.h"
|
|
#include "gstmemchunk.h"
|
|
#include "gsttrashstack.h"
|
|
|
|
#define GST_MEM_CHUNK_AREA(chunk) (((GstMemChunkElement*)(chunk))->area)
|
|
#define GST_MEM_CHUNK_DATA(chunk) ((gpointer)(((GstMemChunkElement*)(chunk)) + 1))
|
|
#define GST_MEM_CHUNK_LINK(mem) ((GstMemChunkElement*)((guint8*)(mem) - sizeof (GstMemChunkElement)))
|
|
|
|
typedef struct _GstMemChunkElement GstMemChunkElement;
|
|
|
|
struct _GstMemChunkElement
|
|
{
|
|
GstTrashStackElement elem; /* make sure we can safely push it on the trashstack */
|
|
gpointer area; /* pointer to data areas */
|
|
};
|
|
|
|
struct _GstMemChunk
|
|
{
|
|
GstTrashStack stack;
|
|
|
|
gchar *name;
|
|
gulong area_size;
|
|
gulong chunk_size;
|
|
gulong atom_size;
|
|
gboolean cleanup;
|
|
};
|
|
|
|
/*******************************************************
|
|
* area size
|
|
* +-------------------------------------------------------+
|
|
* chunk size
|
|
* +-----------------+
|
|
*
|
|
* !next!area|data... !next!area!data.... !next!area!data...
|
|
* ! ^ ! ^ !
|
|
* +------------------+ +-----------------+ +--------> NULL
|
|
*
|
|
*/
|
|
static gboolean
|
|
populate (GstMemChunk *mem_chunk)
|
|
{
|
|
guint8 *area;
|
|
gint i;
|
|
|
|
if (mem_chunk->cleanup)
|
|
return FALSE;
|
|
|
|
area = (guint8 *) g_malloc0 (mem_chunk->area_size);
|
|
|
|
for (i=0; i < mem_chunk->area_size; i += mem_chunk->chunk_size) {
|
|
GST_MEM_CHUNK_AREA (area + i) = area;
|
|
gst_trash_stack_push (&mem_chunk->stack, area + i);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* gst_mem_chunk_new:
|
|
* @name: the name of the chunk
|
|
* @atom_size: the size of the allocated atoms
|
|
* @area_size: the initial size of the memory area
|
|
* @type: the allocation strategy to use
|
|
*
|
|
* Creates a new memchunk that will allocate atom_sized memchunks.
|
|
* The initial area is set to area_size and will grow automatically
|
|
* when it is too small (with a small overhead when that happens)
|
|
*
|
|
* Returns: a new #GstMemChunk
|
|
*/
|
|
GstMemChunk*
|
|
gst_mem_chunk_new (gchar* name, gint atom_size, gulong area_size, gint type)
|
|
{
|
|
GstMemChunk *mem_chunk;
|
|
|
|
g_return_val_if_fail (atom_size > 0, NULL);
|
|
g_return_val_if_fail (area_size >= atom_size, NULL);
|
|
|
|
mem_chunk = g_malloc (sizeof (GstMemChunk));
|
|
|
|
mem_chunk->chunk_size = atom_size + sizeof (GstMemChunkElement);
|
|
area_size = (area_size/atom_size) * mem_chunk->chunk_size;
|
|
|
|
mem_chunk->name = g_strdup (name);
|
|
mem_chunk->atom_size = atom_size;
|
|
mem_chunk->area_size = area_size;
|
|
mem_chunk->cleanup = FALSE;
|
|
gst_trash_stack_init (&mem_chunk->stack);
|
|
|
|
populate (mem_chunk);
|
|
|
|
return mem_chunk;
|
|
}
|
|
|
|
static gboolean
|
|
free_area (gpointer key, gpointer value, gpointer user_data)
|
|
{
|
|
g_free (key);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* gst_mem_chunk_destroy:
|
|
* @mem_chunk: the GstMemChunk to destroy
|
|
*
|
|
* Free the memory allocated by the memchunk
|
|
*/
|
|
void
|
|
gst_mem_chunk_destroy (GstMemChunk *mem_chunk)
|
|
{
|
|
GHashTable *elements = g_hash_table_new (NULL, NULL);
|
|
gpointer data;
|
|
|
|
mem_chunk->cleanup = TRUE;
|
|
|
|
data = gst_mem_chunk_alloc (mem_chunk);
|
|
while (data) {
|
|
GstMemChunkElement *elem = GST_MEM_CHUNK_LINK (data);
|
|
|
|
g_hash_table_insert (elements, GST_MEM_CHUNK_AREA (elem), NULL);
|
|
|
|
data = gst_mem_chunk_alloc (mem_chunk);
|
|
}
|
|
g_hash_table_foreach_remove (elements, free_area, NULL);
|
|
|
|
g_hash_table_destroy (elements);
|
|
g_free (mem_chunk->name);
|
|
g_free (mem_chunk);
|
|
}
|
|
|
|
/**
|
|
* gst_mem_chunk_alloc:
|
|
* @mem_chunk: the mem chunk to use
|
|
*
|
|
* Allocate a new memory region from the chunk. The size
|
|
* of the allocated memory was specified when the memchunk
|
|
* was created.
|
|
*
|
|
* Returns: a pointer to the allocated memory region.
|
|
*/
|
|
gpointer
|
|
gst_mem_chunk_alloc (GstMemChunk *mem_chunk)
|
|
{
|
|
GstMemChunkElement *chunk;
|
|
|
|
g_return_val_if_fail (mem_chunk != NULL, NULL);
|
|
|
|
again:
|
|
chunk = gst_trash_stack_pop (&mem_chunk->stack);
|
|
/* chunk is empty, try to refill */
|
|
if (!chunk) {
|
|
if (populate (mem_chunk))
|
|
goto again;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
return GST_MEM_CHUNK_DATA (chunk);
|
|
}
|
|
|
|
/**
|
|
* gst_mem_chunk_alloc0:
|
|
* @mem_chunk: the mem chunk to use
|
|
*
|
|
* Allocate a new memory region from the chunk. The size
|
|
* of the allocated memory was specified when the memchunk
|
|
* was created. The memory will be set to all zeroes.
|
|
*
|
|
* Returns: a pointer to the allocated memory region.
|
|
*/
|
|
gpointer
|
|
gst_mem_chunk_alloc0 (GstMemChunk *mem_chunk)
|
|
{
|
|
gpointer mem = gst_mem_chunk_alloc (mem_chunk);
|
|
|
|
if (mem)
|
|
memset (mem, 0, mem_chunk->atom_size);
|
|
|
|
return mem;
|
|
}
|
|
|
|
/**
|
|
* gst_mem_chunk_free:
|
|
* @mem_chunk: the mem chunk to use
|
|
* @mem: the memory region to hand back to the chunk
|
|
*
|
|
* Free the memeory region allocated from the chunk.
|
|
*/
|
|
void
|
|
gst_mem_chunk_free (GstMemChunk *mem_chunk, gpointer mem)
|
|
{
|
|
GstMemChunkElement *chunk;
|
|
|
|
g_return_if_fail (mem_chunk != NULL);
|
|
g_return_if_fail (mem != NULL);
|
|
|
|
chunk = GST_MEM_CHUNK_LINK (mem);
|
|
|
|
gst_trash_stack_push (&mem_chunk->stack, chunk);
|
|
}
|