2000-12-28 22:12:02 +00:00
|
|
|
/* GStreamer
|
|
|
|
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
|
|
|
* 2000 Wim Taymans <wtay@chello.be>
|
|
|
|
*
|
|
|
|
* gstbuffer.c: Buffer operations
|
2000-01-30 09:03:00 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
Changes made to the DEBUG system. New header file gstdebug.h holds the stuff to keep it out of gst.h's hair. DEBUG ...
Original commit message from CVS:
Changes made to the DEBUG system. New header file gstdebug.h holds the
stuff to keep it out of gst.h's hair. DEBUG prints out the process id,
cothread id, source filename and line number. Two new macros DEBUG_ENTER
and DEBUG_LEAVE are used to show the entry and exit of a given function.
This eventually might be used to construct call trace graphs, even taking
cothreads into account. This would be quite useful in visualizing the
scheduling mechanism.
Minor changes to various debug messages.
Also sitting in gstdebug.h is a prototypical DEBUG_ENTER that's capable of
performing DEBUG_LEAVE automatically. It does this by utilizing a
little-known GCC extension that allows one to call a function with the
same parameters as the current function. The macro uses this to basically
call itself. A boolean is used to ensure that when it calls itself it
actually runs the body of the function. In the meantime it prints stuff
out before and after the real function, as well as constructing a
debugging string. This can be used eventually to provide call-wide data
on the DEBUG lines, instead of having to replicate data on each call to
DEBUG. More research is needed into how this would most cleanly be fit
into some other chunk of code, like GStreamer (I think of this DEBUG trick
as a separate project, sorta).
Unfortunately, the aforementioned DEBUG trick interacts quite poorly with
cothreads. Almost any time it's used in a function that has anything
remotely to do with a cothread context (as in, it runs in one), a segfault
results from the __builtin_apply call, which is the heart of the whole
thing. If someone who really knows assembly could analyze the resulting
code to see what's really going on, we might find a way to fix either the
macro or the cothreads (I'm thinking that there's something we missed in
constructing the cothreads themselves) so this works in all cases.
In the meantime, please insert both DEBUG_ENTER and DEBUG_LEAVE in your
functions. Be sure to put DEBUG_ENTER after your variable declarations
and before any functional code, not to put the function name in any DEBUG
strings (it's already there, trust me), and put a DEBUG_LEAVE if you care
enough.
Changes are going to happen in the way DEBUGs and other printouts occur,
so stay tuned.
2000-12-04 09:35:08 +00:00
|
|
|
/* this file makes too much noise for most debugging sessions */
|
|
|
|
#define GST_DEBUG_FORCE_DISABLE
|
2000-12-28 22:12:02 +00:00
|
|
|
#include "gst_private.h"
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-12-31 03:21:08 +00:00
|
|
|
#include "gstatomic_impl.h"
|
2002-07-08 19:22:02 +00:00
|
|
|
#include "gstdata_private.h"
|
2000-12-15 01:57:34 +00:00
|
|
|
#include "gstbuffer.h"
|
2002-07-08 19:22:02 +00:00
|
|
|
#include "gstmemchunk.h"
|
|
|
|
#include "gstlog.h"
|
2002-07-24 18:31:12 +00:00
|
|
|
#include "gstbufferpool-default.h"
|
2000-12-28 22:12:02 +00:00
|
|
|
|
2001-10-17 10:21:27 +00:00
|
|
|
GType _gst_buffer_type;
|
2002-07-08 19:22:02 +00:00
|
|
|
GType _gst_buffer_pool_type;
|
2001-10-17 10:21:27 +00:00
|
|
|
|
2001-12-22 21:18:17 +00:00
|
|
|
static gint _gst_buffer_live;
|
2002-07-08 19:22:02 +00:00
|
|
|
static gint _gst_buffer_pool_live;
|
|
|
|
|
|
|
|
static GstMemChunk *chunk;
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
void
|
|
|
|
_gst_buffer_initialize (void)
|
2000-11-11 15:13:50 +00:00
|
|
|
{
|
2002-07-08 19:22:02 +00:00
|
|
|
_gst_buffer_type = g_boxed_type_register_static ("GstBuffer",
|
2002-08-30 14:54:58 +00:00
|
|
|
(GBoxedCopyFunc) gst_data_ref,
|
|
|
|
(GBoxedFreeFunc) gst_data_unref);
|
2002-07-08 19:22:02 +00:00
|
|
|
|
|
|
|
_gst_buffer_pool_type = g_boxed_type_register_static ("GstBufferPool",
|
2002-08-30 14:54:58 +00:00
|
|
|
(GBoxedCopyFunc) gst_data_ref,
|
|
|
|
(GBoxedFreeFunc) gst_data_unref);
|
2001-12-22 21:18:17 +00:00
|
|
|
|
|
|
|
_gst_buffer_live = 0;
|
2002-07-24 20:20:50 +00:00
|
|
|
_gst_buffer_pool_live = 0;
|
2002-07-08 19:22:02 +00:00
|
|
|
|
2002-08-30 14:54:58 +00:00
|
|
|
chunk = gst_mem_chunk_new ("GstBufferChunk", sizeof (GstBuffer),
|
|
|
|
sizeof (GstBuffer) * 200, 0);
|
2002-07-08 19:22:02 +00:00
|
|
|
|
|
|
|
GST_INFO (GST_CAT_BUFFER, "Buffers are initialized now");
|
2001-12-22 21:18:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_buffer_print_stats:
|
|
|
|
*
|
2002-04-17 15:19:56 +00:00
|
|
|
* Logs statistics about live buffers (using g_log).
|
2001-12-22 21:18:17 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
gst_buffer_print_stats (void)
|
|
|
|
{
|
2002-08-30 14:54:58 +00:00
|
|
|
g_log (g_log_domain_gstreamer, G_LOG_LEVEL_INFO, "%d live buffer(s)",
|
|
|
|
_gst_buffer_live);
|
|
|
|
g_log (g_log_domain_gstreamer, G_LOG_LEVEL_INFO, "%d live bufferpool(s)",
|
|
|
|
_gst_buffer_pool_live);
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
static void
|
|
|
|
_gst_buffer_free_to_pool (GstBuffer *buffer)
|
2000-11-11 15:13:50 +00:00
|
|
|
{
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBufferPool *pool = buffer->pool;
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-07-24 18:31:12 +00:00
|
|
|
pool->buffer_free (pool, buffer, pool->user_data);
|
2001-10-17 10:21:27 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
gst_data_unref (GST_DATA (pool));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_gst_buffer_sub_free (GstBuffer *buffer)
|
|
|
|
{
|
|
|
|
gst_data_unref (GST_DATA (buffer->pool_private));
|
|
|
|
|
|
|
|
GST_BUFFER_DATA (buffer) = NULL;
|
|
|
|
GST_BUFFER_SIZE (buffer) = 0;
|
|
|
|
|
|
|
|
_GST_DATA_DISPOSE (GST_DATA (buffer));
|
|
|
|
|
|
|
|
gst_mem_chunk_free (chunk, GST_DATA (buffer));
|
|
|
|
_gst_buffer_live--;
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
2000-09-14 20:31:03 +00:00
|
|
|
/**
|
2002-07-13 23:12:22 +00:00
|
|
|
* gst_buffer_default_free:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @buffer: a #GstBuffer to free.
|
2000-09-14 20:31:03 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Frees the memory associated with the buffer including the buffer data,
|
2002-07-08 19:22:02 +00:00
|
|
|
* unless the GST_BUFFER_DONTFREE flags was set or the buffer data is NULL.
|
2002-08-30 14:54:58 +00:00
|
|
|
* This function is used by buffer pools.
|
2000-09-14 20:31:03 +00:00
|
|
|
*/
|
2002-07-08 19:22:02 +00:00
|
|
|
void
|
2002-07-13 23:12:22 +00:00
|
|
|
gst_buffer_default_free (GstBuffer *buffer)
|
2000-08-14 10:55:35 +00:00
|
|
|
{
|
2002-11-22 23:15:14 +00:00
|
|
|
g_return_if_fail (buffer != NULL);
|
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
/* free our data */
|
|
|
|
if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_DONTFREE) && GST_BUFFER_DATA (buffer))
|
|
|
|
g_free (GST_BUFFER_DATA (buffer));
|
2001-08-27 04:19:58 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
/* set to safe values */
|
|
|
|
GST_BUFFER_DATA (buffer) = NULL;
|
|
|
|
GST_BUFFER_SIZE (buffer) = 0;
|
2001-10-17 10:21:27 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
_GST_DATA_DISPOSE (GST_DATA (buffer));
|
|
|
|
|
|
|
|
gst_mem_chunk_free (chunk, GST_DATA (buffer));
|
|
|
|
_gst_buffer_live--;
|
2000-08-14 10:55:35 +00:00
|
|
|
}
|
|
|
|
|
2002-07-24 18:31:12 +00:00
|
|
|
static GstBuffer*
|
|
|
|
_gst_buffer_copy_from_pool (GstBuffer *buffer)
|
|
|
|
{
|
|
|
|
return buffer->pool->buffer_copy (buffer->pool, buffer, buffer->pool->user_data);
|
|
|
|
}
|
|
|
|
|
2000-01-30 09:03:00 +00:00
|
|
|
/**
|
2002-07-13 23:12:22 +00:00
|
|
|
* gst_buffer_default_copy:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @buffer: a #GstBuffer to make a copy of.
|
2000-01-30 09:03:00 +00:00
|
|
|
*
|
2002-07-08 19:22:02 +00:00
|
|
|
* Make a full newly allocated copy of the given buffer, data and all.
|
2002-08-30 14:54:58 +00:00
|
|
|
* This function is used by buffer pools.
|
2000-01-30 09:03:00 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Returns: the new #GstBuffer.
|
2000-01-30 09:03:00 +00:00
|
|
|
*/
|
2000-11-11 15:13:50 +00:00
|
|
|
GstBuffer*
|
2002-07-13 23:12:22 +00:00
|
|
|
gst_buffer_default_copy (GstBuffer *buffer)
|
2000-11-11 15:13:50 +00:00
|
|
|
{
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer *copy;
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-11-22 23:15:14 +00:00
|
|
|
g_return_val_if_fail (buffer != NULL, NULL);
|
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
/* create a fresh new buffer */
|
|
|
|
copy = gst_buffer_new ();
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
/* we simply copy everything from our parent */
|
2002-08-30 14:54:58 +00:00
|
|
|
GST_BUFFER_DATA (copy) = g_memdup (GST_BUFFER_DATA (buffer),
|
|
|
|
GST_BUFFER_SIZE (buffer));
|
2002-07-08 19:22:02 +00:00
|
|
|
GST_BUFFER_SIZE (copy) = GST_BUFFER_SIZE (buffer);
|
|
|
|
GST_BUFFER_MAXSIZE (copy) = GST_BUFFER_MAXSIZE (buffer);
|
|
|
|
GST_BUFFER_TIMESTAMP (copy) = GST_BUFFER_TIMESTAMP (buffer);
|
|
|
|
GST_BUFFER_OFFSET (copy) = GST_BUFFER_OFFSET (buffer);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
return copy;
|
|
|
|
}
|
2001-10-17 10:21:27 +00:00
|
|
|
|
2000-08-14 10:55:35 +00:00
|
|
|
/**
|
2002-07-08 19:22:02 +00:00
|
|
|
* gst_buffer_new:
|
2000-08-14 10:55:35 +00:00
|
|
|
*
|
2002-07-08 19:22:02 +00:00
|
|
|
* Creates a newly allocated buffer without any data.
|
2000-08-14 10:55:35 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Returns: the new #GstBuffer.
|
2000-08-14 10:55:35 +00:00
|
|
|
*/
|
2000-11-11 15:13:50 +00:00
|
|
|
GstBuffer*
|
2002-07-08 19:22:02 +00:00
|
|
|
gst_buffer_new (void)
|
2000-11-11 15:13:50 +00:00
|
|
|
{
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer *new;
|
|
|
|
|
|
|
|
new = gst_mem_chunk_alloc0 (chunk);
|
|
|
|
_gst_buffer_live++;
|
2000-08-14 10:55:35 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
_GST_DATA_INIT (GST_DATA (new),
|
|
|
|
_gst_buffer_type,
|
|
|
|
0,
|
2002-07-13 23:12:22 +00:00
|
|
|
(GstDataFreeFunction) gst_buffer_default_free,
|
|
|
|
(GstDataCopyFunction) gst_buffer_default_copy);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
GST_BUFFER_BUFFERPOOL (new) = NULL;
|
|
|
|
GST_BUFFER_POOL_PRIVATE (new) = NULL;
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
return new;
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
2000-03-27 19:53:43 +00:00
|
|
|
/**
|
2002-07-08 19:22:02 +00:00
|
|
|
* gst_buffer_new_and_alloc:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @size: the size of the new buffer's data.
|
2002-07-08 19:22:02 +00:00
|
|
|
*
|
|
|
|
* Creates a newly allocated buffer with data of the given size.
|
2000-03-27 19:53:43 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Returns: the new #GstBuffer.
|
2000-03-27 19:53:43 +00:00
|
|
|
*/
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer*
|
|
|
|
gst_buffer_new_and_alloc (guint size)
|
2000-11-11 15:13:50 +00:00
|
|
|
{
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer *new;
|
|
|
|
|
|
|
|
new = gst_buffer_new ();
|
|
|
|
|
|
|
|
GST_BUFFER_DATA (new) = g_malloc (size);
|
|
|
|
GST_BUFFER_SIZE (new) = size;
|
|
|
|
|
|
|
|
return new;
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
2001-10-21 18:00:31 +00:00
|
|
|
/**
|
2002-07-08 19:22:02 +00:00
|
|
|
* gst_buffer_new_from_pool:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @pool: a #GstBufferPool to use.
|
|
|
|
* @offset: the offset of the new buffer.
|
|
|
|
* @size: the size of the new buffer.
|
2001-10-21 18:00:31 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Creates a newly allocated buffer using the specified buffer pool,
|
|
|
|
* offset and size.
|
2002-07-08 19:22:02 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Returns: the new #GstBuffer, or NULL if there was an error.
|
2001-10-21 18:00:31 +00:00
|
|
|
*/
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer*
|
2002-12-19 21:31:03 +00:00
|
|
|
gst_buffer_new_from_pool (GstBufferPool *pool,
|
2002-12-21 14:28:42 +00:00
|
|
|
guint64 offset, guint size)
|
2001-10-21 18:00:31 +00:00
|
|
|
{
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer *buffer;
|
|
|
|
|
2002-07-24 18:31:12 +00:00
|
|
|
g_return_val_if_fail (pool != NULL, NULL);
|
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
buffer = pool->buffer_new (pool, offset, size, pool->user_data);
|
|
|
|
if (!buffer)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
GST_BUFFER_BUFFERPOOL (buffer) = pool;
|
|
|
|
gst_data_ref (GST_DATA (pool));
|
|
|
|
|
|
|
|
/* override the buffer refcount functions with those from the pool (if any) */
|
|
|
|
if (pool->buffer_free)
|
2002-07-24 18:31:12 +00:00
|
|
|
GST_DATA (buffer)->free = (GstDataFreeFunction)_gst_buffer_free_to_pool;
|
2002-07-08 19:22:02 +00:00
|
|
|
if (pool->buffer_copy)
|
2002-07-24 18:31:12 +00:00
|
|
|
GST_DATA (buffer)->copy = (GstDataCopyFunction)_gst_buffer_copy_from_pool;
|
2002-07-08 19:22:02 +00:00
|
|
|
|
|
|
|
return buffer;
|
2001-10-21 18:00:31 +00:00
|
|
|
}
|
|
|
|
|
2000-03-27 19:53:43 +00:00
|
|
|
/**
|
2002-07-08 19:22:02 +00:00
|
|
|
* gst_buffer_create_sub:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @parent: a parent #GstBuffer to create a subbuffer from.
|
|
|
|
* @offset: the offset into parent #GstBuffer.
|
|
|
|
* @size: the size of the new #GstBuffer sub-buffer (with size > 0).
|
2000-03-27 19:53:43 +00:00
|
|
|
*
|
2002-07-08 19:22:02 +00:00
|
|
|
* Creates a sub-buffer from the parent at a given offset.
|
|
|
|
* This sub-buffer uses the actual memory space of the parent buffer.
|
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Returns: the new #GstBuffer, or NULL if there was an error.
|
2000-03-27 19:53:43 +00:00
|
|
|
*/
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer*
|
|
|
|
gst_buffer_create_sub (GstBuffer *parent, guint offset, guint size)
|
2000-11-11 15:13:50 +00:00
|
|
|
{
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer *buffer;
|
|
|
|
gpointer buffer_data;
|
|
|
|
guint64 parent_offset;
|
|
|
|
|
|
|
|
g_return_val_if_fail (parent != NULL, NULL);
|
|
|
|
g_return_val_if_fail (GST_BUFFER_REFCOUNT_VALUE (parent) > 0, NULL);
|
|
|
|
g_return_val_if_fail (size > 0, NULL);
|
|
|
|
g_return_val_if_fail (parent->size >= offset + size, NULL);
|
|
|
|
|
|
|
|
/* remember the data for the new buffer */
|
|
|
|
buffer_data = parent->data + offset;
|
|
|
|
parent_offset = GST_BUFFER_OFFSET (parent);
|
|
|
|
/* make sure we're child not child from a child buffer */
|
|
|
|
while (GST_BUFFER_FLAG_IS_SET (parent, GST_BUFFER_SUBBUFFER)) {
|
|
|
|
parent = GST_BUFFER (parent->pool_private);
|
|
|
|
}
|
|
|
|
/* ref the real parent */
|
|
|
|
gst_data_ref (GST_DATA (parent));
|
|
|
|
/* make sure nobody overwrites data in the parent */
|
|
|
|
if (!GST_DATA_IS_READONLY (parent))
|
|
|
|
GST_DATA_FLAG_SET(parent, GST_DATA_READONLY);
|
|
|
|
|
|
|
|
/* create the new buffer */
|
|
|
|
buffer = gst_mem_chunk_alloc0 (chunk);
|
|
|
|
_gst_buffer_live++;
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-08-30 14:54:58 +00:00
|
|
|
/* make sure nobody overwrites data in the new buffer
|
|
|
|
* by setting the READONLY flag */
|
2002-07-08 19:22:02 +00:00
|
|
|
_GST_DATA_INIT (GST_DATA (buffer),
|
|
|
|
_gst_buffer_type,
|
|
|
|
GST_DATA_FLAG_SHIFT (GST_BUFFER_SUBBUFFER) |
|
|
|
|
GST_DATA_FLAG_SHIFT (GST_DATA_READONLY),
|
|
|
|
(GstDataFreeFunction) _gst_buffer_sub_free,
|
2002-07-13 23:12:22 +00:00
|
|
|
(GstDataCopyFunction) gst_buffer_default_copy);
|
2002-07-08 19:22:02 +00:00
|
|
|
|
|
|
|
GST_BUFFER_OFFSET (buffer) = parent_offset + offset;
|
|
|
|
GST_BUFFER_TIMESTAMP (buffer) = -1;
|
|
|
|
GST_BUFFER_BUFFERPOOL (buffer) = NULL;
|
|
|
|
GST_BUFFER_POOL_PRIVATE (buffer) = parent;
|
|
|
|
|
|
|
|
/* set the right values in the child */
|
|
|
|
buffer->data = buffer_data;
|
|
|
|
buffer->size = size;
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
return buffer;
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
|
2001-04-22 01:41:40 +00:00
|
|
|
/**
|
2002-07-08 19:22:02 +00:00
|
|
|
* gst_buffer_merge:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @buf1: a first source #GstBuffer to merge.
|
|
|
|
* @buf2: the second source #GstBuffer to merge.
|
2001-04-22 01:41:40 +00:00
|
|
|
*
|
2002-07-08 19:22:02 +00:00
|
|
|
* Create a new buffer that is the concatenation of the two source
|
|
|
|
* buffers. The original source buffers will not be modified or
|
|
|
|
* unref'd.
|
2001-04-22 01:41:40 +00:00
|
|
|
*
|
2002-07-13 23:12:22 +00:00
|
|
|
* Internally is nothing more than a specialized gst_buffer_span(),
|
2002-07-08 19:22:02 +00:00
|
|
|
* so the same optimizations can occur.
|
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Returns: the new #GstBuffer that's the concatenation of the source buffers.
|
2001-04-22 01:41:40 +00:00
|
|
|
*/
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer*
|
|
|
|
gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2)
|
2001-04-22 01:30:19 +00:00
|
|
|
{
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer *result;
|
2002-11-22 23:15:14 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
/* we're just a specific case of the more general gst_buffer_span() */
|
|
|
|
result = gst_buffer_span (buf1, 0, buf2, buf1->size + buf2->size);
|
2001-04-22 01:30:19 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
return result;
|
2001-04-22 01:30:19 +00:00
|
|
|
}
|
2001-08-11 08:25:05 +00:00
|
|
|
|
2001-10-21 18:00:31 +00:00
|
|
|
/**
|
|
|
|
* gst_buffer_is_span_fast:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @buf1: a first source #GstBuffer.
|
|
|
|
* @buf2: the second source #GstBuffer.
|
2001-09-10 19:46:01 +00:00
|
|
|
*
|
2002-07-13 23:12:22 +00:00
|
|
|
* Determines whether a gst_buffer_span() is free (as in free beer),
|
2002-04-12 09:38:47 +00:00
|
|
|
* or requires a memcpy.
|
2001-09-10 19:46:01 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Returns: TRUE if the buffers are contiguous,
|
|
|
|
* FALSE if a copy would be required.
|
2001-09-10 19:46:01 +00:00
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2)
|
|
|
|
{
|
2002-11-22 23:15:14 +00:00
|
|
|
g_return_val_if_fail (buf1 != NULL && buf2 != NULL, FALSE);
|
2002-07-08 19:22:02 +00:00
|
|
|
g_return_val_if_fail (GST_BUFFER_REFCOUNT_VALUE (buf1) > 0, FALSE);
|
|
|
|
g_return_val_if_fail (GST_BUFFER_REFCOUNT_VALUE (buf2) > 0, FALSE);
|
2001-10-17 10:21:27 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
/* it's only fast if we have subbuffers of the same parent */
|
|
|
|
return ((GST_BUFFER_FLAG_IS_SET (buf1, GST_BUFFER_SUBBUFFER)) &&
|
|
|
|
(GST_BUFFER_FLAG_IS_SET (buf2, GST_BUFFER_SUBBUFFER)) &&
|
|
|
|
(buf1->pool_private == buf2->pool_private) &&
|
2001-09-10 19:46:01 +00:00
|
|
|
((buf1->data + buf1->size) == buf2->data));
|
|
|
|
}
|
|
|
|
|
2001-09-04 04:34:32 +00:00
|
|
|
/**
|
|
|
|
* gst_buffer_span:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @buf1: a first source #GstBuffer to merge.
|
|
|
|
* @offset: the offset in the first buffer from where the new
|
|
|
|
* buffer should start.
|
|
|
|
* @buf2: the second source #GstBuffer to merge.
|
|
|
|
* @len: the total length of the new buffer.
|
2001-09-04 04:34:32 +00:00
|
|
|
*
|
2002-04-17 15:19:56 +00:00
|
|
|
* Creates a new buffer that consists of part of buf1 and buf2.
|
2001-09-04 04:34:32 +00:00
|
|
|
* Logically, buf1 and buf2 are concatenated into a single larger
|
|
|
|
* buffer, and a new buffer is created at the given offset inside
|
|
|
|
* this space, with a given length.
|
|
|
|
*
|
|
|
|
* If the two source buffers are children of the same larger buffer,
|
|
|
|
* and are contiguous, the new buffer will be a child of the shared
|
2002-07-13 23:12:22 +00:00
|
|
|
* parent, and thus no copying is necessary. you can use
|
|
|
|
* gst_buffer_is_span_fast() to determine if a memcpy will be needed.
|
2001-09-04 04:34:32 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Returns: the new #GstBuffer that spans the two source buffers.
|
2001-09-04 04:34:32 +00:00
|
|
|
*/
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer*
|
2001-08-11 08:25:05 +00:00
|
|
|
gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
|
|
|
|
{
|
|
|
|
GstBuffer *newbuf;
|
|
|
|
|
2002-11-22 23:15:14 +00:00
|
|
|
g_return_val_if_fail (buf1 != NULL && buf2 != NULL, FALSE);
|
2002-07-08 19:22:02 +00:00
|
|
|
g_return_val_if_fail (GST_BUFFER_REFCOUNT_VALUE (buf1) > 0, NULL);
|
|
|
|
g_return_val_if_fail (GST_BUFFER_REFCOUNT_VALUE (buf2) > 0, NULL);
|
|
|
|
g_return_val_if_fail (len > 0, NULL);
|
2001-08-11 08:25:05 +00:00
|
|
|
|
2001-12-14 22:59:21 +00:00
|
|
|
/* if the two buffers have the same parent and are adjacent */
|
2002-07-13 23:12:22 +00:00
|
|
|
if (gst_buffer_is_span_fast (buf1, buf2)) {
|
2002-07-08 19:22:02 +00:00
|
|
|
GstBuffer *parent = GST_BUFFER (buf1->pool_private);
|
2001-12-14 22:59:21 +00:00
|
|
|
/* we simply create a subbuffer of the common parent */
|
2002-08-30 14:54:58 +00:00
|
|
|
newbuf = gst_buffer_create_sub (parent,
|
|
|
|
buf1->data - parent->data + offset, len);
|
2001-08-11 08:25:05 +00:00
|
|
|
}
|
2001-10-17 10:21:27 +00:00
|
|
|
else {
|
2002-12-01 01:39:35 +00:00
|
|
|
GST_DEBUG (GST_CAT_BUFFER, "slow path taken while spanning buffers %p and %p",
|
|
|
|
buf1, buf2);
|
2001-12-14 22:59:21 +00:00
|
|
|
/* otherwise we simply have to brute-force copy the buffers */
|
2002-07-08 19:22:02 +00:00
|
|
|
newbuf = gst_buffer_new_and_alloc (len);
|
|
|
|
|
|
|
|
/* copy relevant stuff from data struct of buffer1 */
|
|
|
|
GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET (buf1) + offset;
|
2001-08-11 08:25:05 +00:00
|
|
|
|
2001-12-14 22:59:21 +00:00
|
|
|
/* copy the first buffer's data across */
|
2002-07-08 19:22:02 +00:00
|
|
|
memcpy (newbuf->data, buf1->data + offset, buf1->size - offset);
|
2001-12-14 22:59:21 +00:00
|
|
|
/* copy the second buffer's data across */
|
2002-08-30 14:54:58 +00:00
|
|
|
memcpy (newbuf->data + (buf1->size - offset), buf2->data,
|
|
|
|
len - (buf1->size - offset));
|
2001-10-17 10:21:27 +00:00
|
|
|
}
|
2002-07-13 23:12:22 +00:00
|
|
|
/* if the offset is 0, the new buffer has the same timestamp as buf1 */
|
|
|
|
if (offset == 0)
|
|
|
|
GST_BUFFER_TIMESTAMP (newbuf) = GST_BUFFER_TIMESTAMP (buf1);
|
2001-08-11 08:25:05 +00:00
|
|
|
|
|
|
|
return newbuf;
|
|
|
|
}
|
|
|
|
|
2002-12-14 13:02:16 +00:00
|
|
|
/**
|
|
|
|
* gst_buffer_pool_default_free:
|
|
|
|
* @pool: a #GstBufferPool to free.
|
|
|
|
*
|
|
|
|
* Frees the memory associated with the bufferpool.
|
|
|
|
*/
|
2002-07-24 18:31:12 +00:00
|
|
|
void
|
|
|
|
gst_buffer_pool_default_free (GstBufferPool *pool)
|
2002-07-08 19:22:02 +00:00
|
|
|
{
|
2002-11-22 23:15:14 +00:00
|
|
|
g_return_if_fail (pool != NULL);
|
|
|
|
|
2002-07-13 23:12:22 +00:00
|
|
|
_GST_DATA_DISPOSE (GST_DATA (pool));
|
|
|
|
g_free (pool);
|
2002-07-08 19:22:02 +00:00
|
|
|
_gst_buffer_pool_live--;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_buffer_pool_new:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @free: the #GstDataFreeFunction to free the buffer pool.
|
|
|
|
* @copy: the #GstDataCopyFunction to copy the buffer pool.
|
|
|
|
* @buffer_new: the #GstBufferPoolBufferNewFunction to create a new buffer
|
|
|
|
* from this pool
|
|
|
|
* @buffer_copy: the #GstBufferPoolBufferCopyFunction to copy a buffer
|
|
|
|
* from this pool
|
|
|
|
* @buffer_free: the #GstBufferPoolBufferFreeFunction to free a buffer
|
|
|
|
* in this pool
|
|
|
|
* @user_data: the user data gpointer passed to buffer_* functions.
|
2002-07-08 19:22:02 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Creates a new buffer pool with the given functions.
|
2002-07-08 19:22:02 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Returns: a new #GstBufferPool, or NULL on error.
|
2002-07-08 19:22:02 +00:00
|
|
|
*/
|
|
|
|
GstBufferPool*
|
|
|
|
gst_buffer_pool_new (GstDataFreeFunction free,
|
|
|
|
GstDataCopyFunction copy,
|
|
|
|
GstBufferPoolBufferNewFunction buffer_new,
|
|
|
|
GstBufferPoolBufferCopyFunction buffer_copy,
|
|
|
|
GstBufferPoolBufferFreeFunction buffer_free,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GstBufferPool *pool;
|
|
|
|
|
|
|
|
/* we need at least a buffer_new function */
|
|
|
|
g_return_val_if_fail (buffer_new != NULL, NULL);
|
|
|
|
|
|
|
|
pool = g_new0 (GstBufferPool, 1);
|
|
|
|
_gst_buffer_pool_live++;
|
2002-07-24 18:31:12 +00:00
|
|
|
|
|
|
|
GST_DEBUG (GST_CAT_BUFFER, "allocating new buffer pool %p\n", pool);
|
2002-07-08 19:22:02 +00:00
|
|
|
|
|
|
|
/* init data struct */
|
|
|
|
_GST_DATA_INIT (GST_DATA (pool),
|
|
|
|
_gst_buffer_pool_type,
|
|
|
|
0,
|
2002-07-24 18:31:12 +00:00
|
|
|
(free ? free : (GstDataFreeFunction) gst_buffer_pool_default_free),
|
2002-07-08 19:22:02 +00:00
|
|
|
copy);
|
|
|
|
|
|
|
|
/* set functions */
|
|
|
|
pool->buffer_new = buffer_new;
|
|
|
|
pool->buffer_copy = buffer_copy;
|
|
|
|
pool->buffer_free = buffer_free;
|
|
|
|
pool->user_data = user_data;
|
|
|
|
|
|
|
|
return pool;
|
|
|
|
}
|
2001-08-11 08:25:05 +00:00
|
|
|
|
2001-09-04 04:34:32 +00:00
|
|
|
/**
|
2002-07-08 19:22:02 +00:00
|
|
|
* gst_buffer_pool_is_active:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @pool: the #GstBufferPool to query.
|
2001-09-04 04:34:32 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Queries if the given buffer pool is active.
|
2001-09-04 04:34:32 +00:00
|
|
|
*
|
2002-07-08 19:22:02 +00:00
|
|
|
* Returns: TRUE if the pool is active.
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
gst_buffer_pool_is_active (GstBufferPool *pool)
|
|
|
|
{
|
2002-11-22 23:15:14 +00:00
|
|
|
g_return_val_if_fail (pool != NULL, FALSE);
|
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
return pool->active;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_buffer_pool_set_active:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @pool: a #GstBufferPool to set the activity status on.
|
|
|
|
* @active: the new status of the pool.
|
2001-09-04 04:34:32 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Sets the given pool to the active or inactive state depending on the
|
|
|
|
* active parameter.
|
2001-09-04 04:34:32 +00:00
|
|
|
*/
|
2002-07-08 19:22:02 +00:00
|
|
|
void
|
|
|
|
gst_buffer_pool_set_active (GstBufferPool *pool, gboolean active)
|
2001-08-11 08:25:05 +00:00
|
|
|
{
|
2002-11-22 23:15:14 +00:00
|
|
|
g_return_if_fail (pool != NULL);
|
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
pool->active = active;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_buffer_pool_set_user_data:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @pool: the #GstBufferPool to set the user data for.
|
|
|
|
* @user_data: the user_data to set on the buffer pool.
|
2002-07-08 19:22:02 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Sets the given user data on the buffer pool.
|
2002-07-08 19:22:02 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
gst_buffer_pool_set_user_data (GstBufferPool *pool, gpointer user_data)
|
|
|
|
{
|
2002-11-22 23:15:14 +00:00
|
|
|
g_return_if_fail (pool != NULL);
|
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
pool->user_data = user_data;
|
|
|
|
}
|
2001-12-04 22:12:50 +00:00
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
/**
|
|
|
|
* gst_buffer_pool_get_user_data:
|
2002-08-30 14:54:58 +00:00
|
|
|
* @pool: the #GstBufferPool to get the user data for.
|
2002-07-08 19:22:02 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Gets the user data of the buffer pool.
|
2002-07-08 19:22:02 +00:00
|
|
|
*
|
2002-08-30 14:54:58 +00:00
|
|
|
* Returns: the user data associated with this buffer pool.
|
2002-07-08 19:22:02 +00:00
|
|
|
*/
|
|
|
|
gpointer
|
|
|
|
gst_buffer_pool_get_user_data (GstBufferPool *pool)
|
|
|
|
{
|
2002-11-22 23:15:14 +00:00
|
|
|
g_return_val_if_fail (pool != NULL, NULL);
|
|
|
|
|
2002-07-08 19:22:02 +00:00
|
|
|
return pool->user_data;
|
|
|
|
}
|
2001-12-04 22:12:50 +00:00
|
|
|
|