gstbufferlist.c 6.79 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/* GStreamer
 * Copyright (C) 2009 Axis Communications <dev-gstreamer at axis dot com>
 * @author Jonas Holmberg <jonas dot holmberg at axis dot com>
 *
 * gstbufferlist.c: Buffer list
 *
 * 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.
 */

/**
 * SECTION:gstbufferlist
Wim Taymans's avatar
Wim Taymans committed
25
 * @short_description: Lists of buffers for data-passing
26 27
 * @see_also: #GstPad, #GstMiniObject
 *
Wim Taymans's avatar
Wim Taymans committed
28
 * Buffer lists are an object containing a list of buffers.
29 30
 *
 * Buffer lists are created with gst_buffer_list_new() and filled with data
Wim Taymans's avatar
Wim Taymans committed
31
 * using a gst_buffer_list_insert().
32 33 34 35 36 37 38 39 40
 *
 */
#include "gst_private.h"

#include "gstbuffer.h"
#include "gstbufferlist.h"

#define GST_CAT_DEFAULT GST_CAT_BUFFER_LIST

Wim Taymans's avatar
Wim Taymans committed
41 42 43 44
/**
 * GstBufferList:
 *
 * Opaque list of grouped buffers.
45 46
 *
 * Since: 0.10.24
Wim Taymans's avatar
Wim Taymans committed
47 48 49 50 51
 */
struct _GstBufferList
{
  GstMiniObject mini_object;

Wim Taymans's avatar
Wim Taymans committed
52
  GArray *array;
53 54
};

Wim Taymans's avatar
Wim Taymans committed
55
GType _gst_buffer_list_type = 0;
56

57
GST_DEFINE_MINI_OBJECT_TYPE (GstBufferList, gst_buffer_list);
Wim Taymans's avatar
Wim Taymans committed
58

59
void
60
_priv_gst_buffer_list_initialize (void)
61
{
Wim Taymans's avatar
Wim Taymans committed
62
  _gst_buffer_list_type = gst_buffer_list_get_type ();
63 64 65 66 67
}

static GstBufferList *
_gst_buffer_list_copy (GstBufferList * list)
{
Wim Taymans's avatar
Wim Taymans committed
68 69
  GstBufferList *copy;
  guint i, len;
70

Wim Taymans's avatar
Wim Taymans committed
71 72
  len = list->array->len;
  copy = gst_buffer_list_sized_new (len);
73

Wim Taymans's avatar
Wim Taymans committed
74 75 76 77 78 79 80
  /* add and ref all buffers in the array */
  for (i = 0; i < len; i++) {
    GstBuffer *buf = g_array_index (list->array, GstBuffer *, i);
    buf = gst_buffer_ref (buf);
    g_array_append_val (copy->array, buf);
  }
  return copy;
81 82 83
}

static void
84
_gst_buffer_list_free (GstBufferList * list)
85
{
Wim Taymans's avatar
Wim Taymans committed
86
  guint i, len;
87 88
  GST_LOG ("free %p", list);

Wim Taymans's avatar
Wim Taymans committed
89 90 91 92 93
  /* unrefs all buffers too */
  len = list->array->len;
  for (i = 0; i < len; i++)
    gst_buffer_unref (g_array_index (list->array, GstBuffer *, i));
  g_array_free (list->array, TRUE);
94

Wim Taymans's avatar
Wim Taymans committed
95 96 97 98
  g_slice_free1 (GST_MINI_OBJECT_SIZE (list), list);
}

static void
Wim Taymans's avatar
Wim Taymans committed
99
gst_buffer_list_init (GstBufferList * list, gsize size, guint asize)
Wim Taymans's avatar
Wim Taymans committed
100 101 102 103 104 105
{
  gst_mini_object_init (GST_MINI_OBJECT_CAST (list), _gst_buffer_list_type,
      size);

  list->mini_object.copy = (GstMiniObjectCopyFunction) _gst_buffer_list_copy;
  list->mini_object.free = (GstMiniObjectFreeFunction) _gst_buffer_list_free;
106

Wim Taymans's avatar
Wim Taymans committed
107
  list->array = g_array_sized_new (FALSE, FALSE, sizeof (GstBuffer *), asize);
108 109

  GST_LOG ("init %p", list);
110 111 112
}

/**
Wim Taymans's avatar
Wim Taymans committed
113 114
 * gst_buffer_list_sized_new:
 * @size: an initial reserved size
115 116
 *
 * Creates a new, empty #GstBufferList. The caller is responsible for unreffing
Wim Taymans's avatar
Wim Taymans committed
117 118
 * the returned #GstBufferList. The list will have @size space preallocated so
 * that memory reallocations can be avoided.
119
 *
120 121 122 123
 * Free-function: gst_buffer_list_unref
 *
 * Returns: (transfer full): the new #GstBufferList. gst_buffer_list_unref()
 *     after usage.
124 125
 *
 * Since: 0.10.24
126 127
 */
GstBufferList *
Wim Taymans's avatar
Wim Taymans committed
128
gst_buffer_list_sized_new (guint size)
129 130 131
{
  GstBufferList *list;

132 133
  list = g_slice_new0 (GstBufferList);

134 135
  GST_LOG ("new %p", list);

Wim Taymans's avatar
Wim Taymans committed
136
  gst_buffer_list_init (list, sizeof (GstBufferList), size);
Wim Taymans's avatar
Wim Taymans committed
137

138 139 140 141
  return list;
}

/**
Wim Taymans's avatar
Wim Taymans committed
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
 * gst_buffer_list_new:
 *
 * Creates a new, empty #GstBufferList. The caller is responsible for unreffing
 * the returned #GstBufferList.
 *
 * Free-function: gst_buffer_list_unref
 *
 * Returns: (transfer full): the new #GstBufferList. gst_buffer_list_unref()
 *     after usage.
 *
 * Since: 0.10.24
 */
GstBufferList *
gst_buffer_list_new (void)
{
  return gst_buffer_list_sized_new (8);
}

/**
 * gst_buffer_list_len:
162 163
 * @list: a #GstBufferList
 *
Wim Taymans's avatar
Wim Taymans committed
164
 * Returns the number of buffers in @list.
165
 *
Wim Taymans's avatar
Wim Taymans committed
166
 * Returns: the number of buffers in the buffer list
167 168
 *
 * Since: 0.10.24
169 170
 */
guint
Wim Taymans's avatar
Wim Taymans committed
171
gst_buffer_list_len (GstBufferList * list)
172
{
Wim Taymans's avatar
Wim Taymans committed
173
  g_return_val_if_fail (GST_IS_BUFFER_LIST (list), 0);
174

Wim Taymans's avatar
Wim Taymans committed
175
  return list->array->len;
176 177
}

Wim Taymans's avatar
Wim Taymans committed
178 179 180
/**
 * gst_buffer_list_foreach:
 * @list: a #GstBufferList
181
 * @func: (scope call): a #GstBufferListFunc to call
182
 * @user_data: (closure): user data passed to @func
Wim Taymans's avatar
Wim Taymans committed
183 184 185 186 187 188
 *
 * Call @func with @data for each buffer in @list.
 *
 * @func can modify the passed buffer pointer or its contents. The return value
 * of @func define if this function returns or if the remaining buffers in a
 * group should be skipped.
189 190
 *
 * Since: 0.10.24
Wim Taymans's avatar
Wim Taymans committed
191 192 193 194 195
 */
void
gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func,
    gpointer user_data)
{
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
  guint i, len;

  g_return_if_fail (GST_IS_BUFFER_LIST (list));
  g_return_if_fail (func != NULL);

  len = list->array->len;
  for (i = 0; i < len;) {
    GstBuffer *buf, *buf_ret;
    gboolean ret;

    buf = buf_ret = g_array_index (list->array, GstBuffer *, i);
    ret = func (&buf_ret, i, user_data);

    /* Check if the function changed the buffer */
    if (buf != buf_ret) {
      if (buf_ret == NULL) {
        g_array_remove_index (list->array, i);
      } else {
        g_array_index (list->array, GstBuffer *, i) = buf_ret;
      }
    }

    if (!ret)
      break;

    /* If the buffer was not removed by func go to the next buffer */
    if (buf_ret != NULL)
      i++;
  }
Wim Taymans's avatar
Wim Taymans committed
225 226 227 228 229
}

/**
 * gst_buffer_list_get:
 * @list: a #GstBufferList
Wim Taymans's avatar
Wim Taymans committed
230
 * @idx: the index
Wim Taymans's avatar
Wim Taymans committed
231
 *
Wim Taymans's avatar
Wim Taymans committed
232
 * Get the buffer at @idx.
Wim Taymans's avatar
Wim Taymans committed
233
 *
234 235
 * Returns: (transfer none): the buffer at @idx in @group or NULL when there
 *     is no buffer. The buffer remains valid as long as @list is valid.
236 237
 *
 * Since: 0.10.24
Wim Taymans's avatar
Wim Taymans committed
238 239
 */
GstBuffer *
Wim Taymans's avatar
Wim Taymans committed
240
gst_buffer_list_get (GstBufferList * list, guint idx)
Wim Taymans's avatar
Wim Taymans committed
241
{
Wim Taymans's avatar
Wim Taymans committed
242
  GstBuffer *buf;
243

Wim Taymans's avatar
Wim Taymans committed
244 245
  g_return_val_if_fail (GST_IS_BUFFER_LIST (list), NULL);
  g_return_val_if_fail (idx < list->array->len, NULL);
246

Wim Taymans's avatar
Wim Taymans committed
247
  buf = g_array_index (list->array, GstBuffer *, idx);
248

Wim Taymans's avatar
Wim Taymans committed
249
  return buf;
250 251 252
}

/**
Wim Taymans's avatar
Wim Taymans committed
253 254 255 256
 * gst_buffer_list_insert:
 * @list: a #GstBufferList
 * @idx: the index
 * @buffer: a #GstBuffer
257
 *
Wim Taymans's avatar
Wim Taymans committed
258 259
 * Insert @buffer at @idx in @list. Other buffers are moved to make room for
 * this new buffer.
260
 *
Wim Taymans's avatar
Wim Taymans committed
261
 * A -1 value for @idx will append the buffer at the end.
262 263
 */
void
Wim Taymans's avatar
Wim Taymans committed
264
gst_buffer_list_insert (GstBufferList * list, guint idx, GstBuffer * buffer)
265
{
Wim Taymans's avatar
Wim Taymans committed
266
  g_return_if_fail (GST_IS_BUFFER_LIST (list));
267 268
  g_return_if_fail (buffer != NULL);

Wim Taymans's avatar
Wim Taymans committed
269 270 271 272 273
  if (idx == -1)
    g_array_append_val (list->array, buffer);
  else {
    g_return_if_fail (idx < list->array->len);
    g_array_insert_val (list->array, idx, buffer);
Wim Taymans's avatar
Wim Taymans committed
274
  }
275 276 277
}

void
Wim Taymans's avatar
Wim Taymans committed
278
gst_buffer_list_remove (GstBufferList * list, guint idx, guint length)
279
{
Wim Taymans's avatar
Wim Taymans committed
280 281
  g_return_if_fail (GST_IS_BUFFER_LIST (list));
  g_return_if_fail (idx < list->array->len);
282

Wim Taymans's avatar
Wim Taymans committed
283
  g_array_remove_range (list->array, idx, length);
284
}