gstreamer_core/gst/gstbuffer.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
child 29 567bb019e3e3
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
       
     3  *                    2000 Wim Taymans <wtay@chello.be>
       
     4  *
       
     5  * gstbuffer.c: Buffer operations
       
     6  *
       
     7  * This library is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Library General Public
       
     9  * License as published by the Free Software Foundation; either
       
    10  * version 2 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This library is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Library General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Library General Public
       
    18  * License along with this library; if not, write to the
       
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    20  * Boston, MA 02111-1307, USA.
       
    21  */
       
    22 
       
    23 /**
       
    24  * SECTION:gstbuffer
       
    25  * @short_description: Data-passing buffer type, supporting sub-buffers.
       
    26  * @see_also: #GstPad, #GstMiniObject
       
    27  *
       
    28  * Buffers are the basic unit of data transfer in GStreamer.  The #GstBuffer
       
    29  * type provides all the state necessary to define a region of memory as part
       
    30  * of a stream.  Sub-buffers are also supported, allowing a smaller region of a
       
    31  * buffer to become its own buffer, with mechanisms in place to ensure that
       
    32  * neither memory space goes away prematurely.
       
    33  *
       
    34  * Buffers are usually created with gst_buffer_new(). After a buffer has been
       
    35  * created one will typically allocate memory for it and set the size of the
       
    36  * buffer data.  The following example creates a buffer that can hold a given
       
    37  * video frame with a given width, height and bits per plane.
       
    38  * <example>
       
    39  * <title>Creating a buffer for a video frame</title>
       
    40  *   <programlisting>
       
    41  *   GstBuffer *buffer;
       
    42  *   gint size, width, height, bpp;
       
    43  *   ...
       
    44  *   size = width * height * bpp;
       
    45  *   buffer = gst_buffer_new ();
       
    46  *   GST_BUFFER_SIZE (buffer) = size;
       
    47  *   GST_BUFFER_MALLOCDATA (buffer) = g_malloc (size);
       
    48  *   GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);
       
    49  *   ...
       
    50  *   </programlisting>
       
    51  * </example>
       
    52  *
       
    53  * Alternatively, use gst_buffer_new_and_alloc()
       
    54  * to create a buffer with preallocated data of a given size.
       
    55  *
       
    56  * The data pointed to by the buffer can be retrieved with the GST_BUFFER_DATA()
       
    57  * macro. The size of the data can be found with GST_BUFFER_SIZE(). For buffers
       
    58  * of size 0, the data pointer is undefined (usually NULL) and should never be used.
       
    59  *
       
    60  * If an element knows what pad you will push the buffer out on, it should use
       
    61  * gst_pad_alloc_buffer() instead to create a buffer.  This allows downstream
       
    62  * elements to provide special buffers to write in, like hardware buffers.
       
    63  *
       
    64  * A buffer has a pointer to a #GstCaps describing the media type of the data
       
    65  * in the buffer. Attach caps to the buffer with gst_buffer_set_caps(); this
       
    66  * is typically done before pushing out a buffer using gst_pad_push() so that
       
    67  * the downstream element knows the type of the buffer.
       
    68  *
       
    69  * A buffer will usually have a timestamp, and a duration, but neither of these
       
    70  * are guaranteed (they may be set to #GST_CLOCK_TIME_NONE). Whenever a
       
    71  * meaningful value can be given for these, they should be set. The timestamp
       
    72  * and duration are measured in nanoseconds (they are #GstClockTime values).
       
    73  *
       
    74  * A buffer can also have one or both of a start and an end offset. These are
       
    75  * media-type specific. For video buffers, the start offset will generally be
       
    76  * the frame number. For audio buffers, it will be the number of samples
       
    77  * produced so far. For compressed data, it could be the byte offset in a
       
    78  * source or destination file. Likewise, the end offset will be the offset of
       
    79  * the end of the buffer. These can only be meaningfully interpreted if you
       
    80  * know the media type of the buffer (the #GstCaps set on it). Either or both
       
    81  * can be set to #GST_BUFFER_OFFSET_NONE.
       
    82  *
       
    83  * gst_buffer_ref() is used to increase the refcount of a buffer. This must be
       
    84  * done when you want to keep a handle to the buffer after pushing it to the
       
    85  * next element.
       
    86  *
       
    87  * To efficiently create a smaller buffer out of an existing one, you can
       
    88  * use gst_buffer_create_sub().
       
    89  *
       
    90  * If a plug-in wants to modify the buffer data in-place, it should first obtain
       
    91  * a buffer that is safe to modify by using gst_buffer_make_writable().  This
       
    92  * function is optimized so that a copy will only be made when it is necessary.
       
    93  *
       
    94  * A plugin that only wishes to modify the metadata of a buffer, such as the
       
    95  * offset, timestamp or caps, should use gst_buffer_make_metadata_writable(),
       
    96  * which will create a subbuffer of the original buffer to ensure the caller
       
    97  * has sole ownership, and not copy the buffer data.
       
    98  *
       
    99  * Several flags of the buffer can be set and unset with the
       
   100  * GST_BUFFER_FLAG_SET() and GST_BUFFER_FLAG_UNSET() macros. Use
       
   101  * GST_BUFFER_FLAG_IS_SET() to test if a certain #GstBufferFlag is set.
       
   102  *
       
   103  * Buffers can be efficiently merged into a larger buffer with
       
   104  * gst_buffer_merge() and gst_buffer_span() if the gst_buffer_is_span_fast()
       
   105  * function returns TRUE.
       
   106  *
       
   107  * An element should either unref the buffer or push it out on a src pad
       
   108  * using gst_pad_push() (see #GstPad).
       
   109  *
       
   110  * Buffers are usually freed by unreffing them with gst_buffer_unref(). When
       
   111  * the refcount drops to 0, any data pointed to by GST_BUFFER_MALLOCDATA() will
       
   112  * also be freed.
       
   113  *
       
   114  * Last reviewed on August 11th, 2006 (0.10.10)
       
   115  */
       
   116 #include "gst_private.h"
       
   117 
       
   118 #include "gstbuffer.h"
       
   119 #include "gstinfo.h"
       
   120 #include "gstutils.h"
       
   121 #include "gstminiobject.h"
       
   122 
       
   123 static void gst_buffer_init (GTypeInstance * instance, gpointer g_class);
       
   124 static void gst_buffer_class_init (gpointer g_class, gpointer class_data);
       
   125 static void gst_buffer_finalize (GstBuffer * buffer);
       
   126 static GstBuffer *_gst_buffer_copy (GstBuffer * buffer);
       
   127 static GType gst_subbuffer_get_type (void);
       
   128 
       
   129 static GType _gst_subbuffer_type = 0;
       
   130 static GType _gst_buffer_type = 0;
       
   131 
       
   132 static GstMiniObjectClass *parent_class = NULL;
       
   133 #ifdef __SYMBIAN32__
       
   134 EXPORT_C
       
   135 #endif
       
   136 
       
   137 
       
   138 void
       
   139 _gst_buffer_initialize (void)
       
   140 {
       
   141   /* the GstMiniObject types need to be class_ref'd once before it can be
       
   142    * done from multiple threads;
       
   143    * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
       
   144   g_type_class_ref (gst_buffer_get_type ());
       
   145   g_type_class_ref (gst_subbuffer_get_type ());
       
   146 }
       
   147 #ifdef __SYMBIAN32__
       
   148 EXPORT_C
       
   149 #endif
       
   150 
       
   151 
       
   152 GType
       
   153 gst_buffer_get_type (void)
       
   154 {
       
   155   if (G_UNLIKELY (_gst_buffer_type == 0)) {
       
   156     static const GTypeInfo buffer_info = {
       
   157       sizeof (GstBufferClass),
       
   158       NULL,
       
   159       NULL,
       
   160       gst_buffer_class_init,
       
   161       NULL,
       
   162       NULL,
       
   163       sizeof (GstBuffer),
       
   164       0,
       
   165       gst_buffer_init,
       
   166       NULL
       
   167     };
       
   168 
       
   169     _gst_buffer_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
       
   170         "GstBuffer", &buffer_info, 0);
       
   171   }
       
   172   return _gst_buffer_type;
       
   173 }
       
   174 
       
   175 static void
       
   176 gst_buffer_class_init (gpointer g_class, gpointer class_data)
       
   177 {
       
   178   GstBufferClass *buffer_class = GST_BUFFER_CLASS (g_class);
       
   179 
       
   180   parent_class = g_type_class_peek_parent (g_class);
       
   181 
       
   182   buffer_class->mini_object_class.copy =
       
   183       (GstMiniObjectCopyFunction) _gst_buffer_copy;
       
   184   buffer_class->mini_object_class.finalize =
       
   185       (GstMiniObjectFinalizeFunction) gst_buffer_finalize;
       
   186 
       
   187 }
       
   188 
       
   189 static void
       
   190 gst_buffer_finalize (GstBuffer * buffer)
       
   191 {
       
   192   g_return_if_fail (buffer != NULL);
       
   193 
       
   194   GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
       
   195 
       
   196   /* free our data */
       
   197   g_free (buffer->malloc_data);
       
   198 
       
   199   gst_caps_replace (&GST_BUFFER_CAPS (buffer), NULL);
       
   200 
       
   201   GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (buffer));
       
   202 }
       
   203 
       
   204 /**
       
   205  * gst_buffer_copy_metadata:
       
   206  * @dest: a destination #GstBuffer
       
   207  * @src: a source #GstBuffer
       
   208  * @flags: flags indicating what metadata fields should be copied.
       
   209  *
       
   210  * Copies the metadata from @src into @dest. The data, size and mallocdata
       
   211  * fields are not copied.
       
   212  *
       
   213  * @flags indicate which fields will be copied. Use #GST_BUFFER_COPY_ALL to copy
       
   214  * all the metadata fields.
       
   215  *
       
   216  * This function is typically called from a custom buffer copy function after
       
   217  * creating @dest and setting the data, size, mallocdata.
       
   218  *
       
   219  * Since: 0.10.13
       
   220  */
       
   221 #ifdef __SYMBIAN32__
       
   222 EXPORT_C
       
   223 #endif
       
   224 
       
   225 void
       
   226 gst_buffer_copy_metadata (GstBuffer * dest, const GstBuffer * src,
       
   227     GstBufferCopyFlags flags)
       
   228 {
       
   229   g_return_if_fail (dest != NULL);
       
   230   g_return_if_fail (src != NULL);
       
   231 
       
   232   GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p", src, dest);
       
   233 
       
   234   if (flags & GST_BUFFER_COPY_FLAGS) {
       
   235     guint mask;
       
   236 
       
   237     /* copy relevant flags */
       
   238     mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS |
       
   239         GST_BUFFER_FLAG_DELTA_UNIT | GST_BUFFER_FLAG_DISCONT |
       
   240         GST_BUFFER_FLAG_GAP;
       
   241     GST_MINI_OBJECT_FLAGS (dest) |= GST_MINI_OBJECT_FLAGS (src) & mask;
       
   242   }
       
   243 
       
   244   if (flags & GST_BUFFER_COPY_TIMESTAMPS) {
       
   245     GST_BUFFER_TIMESTAMP (dest) = GST_BUFFER_TIMESTAMP (src);
       
   246     GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src);
       
   247     GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src);
       
   248     GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src);
       
   249   }
       
   250 
       
   251   if (flags & GST_BUFFER_COPY_CAPS) {
       
   252     if (GST_BUFFER_CAPS (src))
       
   253       GST_BUFFER_CAPS (dest) = gst_caps_ref (GST_BUFFER_CAPS (src));
       
   254     else
       
   255       GST_BUFFER_CAPS (dest) = NULL;
       
   256   }
       
   257 }
       
   258 
       
   259 static GstBuffer *
       
   260 _gst_buffer_copy (GstBuffer * buffer)
       
   261 {
       
   262   GstBuffer *copy;
       
   263 
       
   264   g_return_val_if_fail (buffer != NULL, NULL);
       
   265 
       
   266   /* create a fresh new buffer */
       
   267   copy = gst_buffer_new ();
       
   268 
       
   269   /* we simply copy everything from our parent */
       
   270   copy->data = g_memdup (buffer->data, buffer->size);
       
   271   /* make sure it gets freed (even if the parent is subclassed, we return a
       
   272      normal buffer) */
       
   273   copy->malloc_data = copy->data;
       
   274   copy->size = buffer->size;
       
   275 
       
   276   gst_buffer_copy_metadata (copy, buffer, GST_BUFFER_COPY_ALL);
       
   277 
       
   278   return copy;
       
   279 }
       
   280 
       
   281 static void
       
   282 gst_buffer_init (GTypeInstance * instance, gpointer g_class)
       
   283 {
       
   284   GstBuffer *buffer;
       
   285 
       
   286   buffer = (GstBuffer *) instance;
       
   287 
       
   288   GST_CAT_LOG (GST_CAT_BUFFER, "init %p", buffer);
       
   289 
       
   290   GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
       
   291   GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
       
   292   GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
       
   293   GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
       
   294 }
       
   295 
       
   296 /**
       
   297  * gst_buffer_new:
       
   298  *
       
   299  * Creates a newly allocated buffer without any data.
       
   300  *
       
   301  * MT safe.
       
   302  * Returns: the new #GstBuffer.
       
   303  */
       
   304 #ifdef __SYMBIAN32__
       
   305 EXPORT_C
       
   306 #endif
       
   307 
       
   308 GstBuffer *
       
   309 gst_buffer_new (void)
       
   310 {
       
   311   GstBuffer *newbuf;
       
   312 
       
   313   newbuf = (GstBuffer *) gst_mini_object_new (_gst_buffer_type);
       
   314 
       
   315   GST_CAT_LOG (GST_CAT_BUFFER, "new %p", newbuf);
       
   316 
       
   317   return newbuf;
       
   318 }
       
   319 
       
   320 /**
       
   321  * gst_buffer_new_and_alloc:
       
   322  * @size: the size of the new buffer's data.
       
   323  *
       
   324  * Creates a newly allocated buffer with data of the given size.
       
   325  * The buffer memory is not cleared. If the requested amount of
       
   326  * memory can't be allocated, the program will abort. Use
       
   327  * gst_buffer_try_new_and_alloc() if you want to handle this case
       
   328  * gracefully or have gotten the size to allocate from an untrusted
       
   329  * source such as a media stream.
       
   330  * 
       
   331  *
       
   332  * Note that when @size == 0, the buffer data pointer will be NULL.
       
   333  *
       
   334  * MT safe.
       
   335  * Returns: the new #GstBuffer.
       
   336  */
       
   337 #ifdef __SYMBIAN32__
       
   338 EXPORT_C
       
   339 #endif
       
   340 
       
   341 GstBuffer *
       
   342 gst_buffer_new_and_alloc (guint size)
       
   343 {
       
   344   GstBuffer *newbuf;
       
   345 
       
   346   newbuf = gst_buffer_new ();
       
   347 
       
   348   newbuf->malloc_data = g_malloc (size);
       
   349   GST_BUFFER_DATA (newbuf) = newbuf->malloc_data;
       
   350   GST_BUFFER_SIZE (newbuf) = size;
       
   351 
       
   352   GST_CAT_LOG (GST_CAT_BUFFER, "new %p of size %d", newbuf, size);
       
   353 
       
   354   return newbuf;
       
   355 }
       
   356 
       
   357 /**
       
   358  * gst_buffer_try_new_and_alloc:
       
   359  * @size: the size of the new buffer's data.
       
   360  *
       
   361  * Tries to create a newly allocated buffer with data of the given size. If
       
   362  * the requested amount of memory can't be allocated, NULL will be returned.
       
   363  * The buffer memory is not cleared.
       
   364  *
       
   365  * Note that when @size == 0, the buffer data pointer will be NULL.
       
   366  *
       
   367  * MT safe.
       
   368  *
       
   369  * Returns: a new #GstBuffer, or NULL if the memory couldn't be allocated.
       
   370  *
       
   371  * Since: 0.10.13
       
   372  */
       
   373 #ifdef __SYMBIAN32__
       
   374 EXPORT_C
       
   375 #endif
       
   376 
       
   377 GstBuffer *
       
   378 gst_buffer_try_new_and_alloc (guint size)
       
   379 {
       
   380   GstBuffer *newbuf;
       
   381   guint8 *malloc_data;
       
   382 
       
   383   malloc_data = g_try_malloc (size);
       
   384 
       
   385   if (G_UNLIKELY (malloc_data == NULL && size != 0)) {
       
   386     GST_CAT_WARNING (GST_CAT_BUFFER, "failed to allocate %d bytes", size);
       
   387     return NULL;
       
   388   }
       
   389 
       
   390   /* FIXME: there's no g_type_try_create_instance() in GObject yet, so this
       
   391    * will still abort if a new GstBuffer structure can't be allocated */
       
   392   newbuf = gst_buffer_new ();
       
   393 
       
   394   GST_BUFFER_MALLOCDATA (newbuf) = malloc_data;
       
   395   GST_BUFFER_DATA (newbuf) = malloc_data;
       
   396   GST_BUFFER_SIZE (newbuf) = size;
       
   397 
       
   398   GST_CAT_LOG (GST_CAT_BUFFER, "new %p of size %d", newbuf, size);
       
   399 
       
   400   return newbuf;
       
   401 }
       
   402 
       
   403 /**
       
   404  * gst_buffer_get_caps:
       
   405  * @buffer: a #GstBuffer.
       
   406  *
       
   407  * Gets the media type of the buffer. This can be NULL if there
       
   408  * is no media type attached to this buffer.
       
   409  *
       
   410  * Returns: a reference to the #GstCaps. unref after usage.
       
   411  * Returns NULL if there were no caps on this buffer.
       
   412  */
       
   413 /* this is not made atomic because if the buffer were reffed from multiple
       
   414  * threads, it would have a refcount > 2 and thus be immutable.
       
   415  */
       
   416 #ifdef __SYMBIAN32__
       
   417 EXPORT_C
       
   418 #endif
       
   419 
       
   420 GstCaps *
       
   421 gst_buffer_get_caps (GstBuffer * buffer)
       
   422 {
       
   423   GstCaps *ret;
       
   424 
       
   425   g_return_val_if_fail (buffer != NULL, NULL);
       
   426 
       
   427   ret = GST_BUFFER_CAPS (buffer);
       
   428 
       
   429   if (ret)
       
   430     gst_caps_ref (ret);
       
   431 
       
   432   return ret;
       
   433 }
       
   434 
       
   435 /**
       
   436  * gst_buffer_set_caps:
       
   437  * @buffer: a #GstBuffer.
       
   438  * @caps: a #GstCaps.
       
   439  *
       
   440  * Sets the media type on the buffer. The refcount of the caps will
       
   441  * be increased and any previous caps on the buffer will be
       
   442  * unreffed.
       
   443  */
       
   444 /* this is not made atomic because if the buffer were reffed from multiple
       
   445  * threads, it would have a refcount > 2 and thus be immutable.
       
   446  */
       
   447 #ifdef __SYMBIAN32__
       
   448 EXPORT_C
       
   449 #endif
       
   450 
       
   451 void
       
   452 gst_buffer_set_caps (GstBuffer * buffer, GstCaps * caps)
       
   453 {
       
   454   g_return_if_fail (buffer != NULL);
       
   455 
       
   456   gst_caps_replace (&GST_BUFFER_CAPS (buffer), caps);
       
   457 }
       
   458 
       
   459 /**
       
   460  * gst_buffer_is_metadata_writable:
       
   461  * @buf: a #GstBuffer
       
   462  *
       
   463  * Similar to gst_buffer_is_writable, but this only ensures that the
       
   464  * refcount of the buffer is 1, indicating that the caller is the sole
       
   465  * owner and can change the buffer metadata, such as caps and timestamps.
       
   466  *
       
   467  * Returns: TRUE if the metadata is writable.
       
   468  */
       
   469 #ifdef __SYMBIAN32__
       
   470 EXPORT_C
       
   471 #endif
       
   472 
       
   473 gboolean
       
   474 gst_buffer_is_metadata_writable (GstBuffer * buf)
       
   475 {
       
   476   return (GST_MINI_OBJECT_REFCOUNT_VALUE (GST_MINI_OBJECT_CAST (buf)) == 1);
       
   477 }
       
   478 
       
   479 /**
       
   480  * gst_buffer_make_metadata_writable:
       
   481  * @buf: a #GstBuffer
       
   482  *
       
   483  * Similar to gst_buffer_make_writable, but does not ensure that the buffer
       
   484  * data array is writable. Instead, this just ensures that the returned buffer
       
   485  * is solely owned by the caller, by creating a subbuffer of the original
       
   486  * buffer if necessary.
       
   487  * 
       
   488  * After calling this function, @buf should not be referenced anymore. The
       
   489  * result of this function has guaranteed writable metadata.
       
   490  *
       
   491  * Returns: A new #GstBuffer with writable metadata.
       
   492  */
       
   493 #ifdef __SYMBIAN32__
       
   494 EXPORT_C
       
   495 #endif
       
   496 
       
   497 GstBuffer *
       
   498 gst_buffer_make_metadata_writable (GstBuffer * buf)
       
   499 {
       
   500   GstBuffer *ret;
       
   501 
       
   502   if (gst_buffer_is_metadata_writable (buf)) {
       
   503     ret = buf;
       
   504   } else {
       
   505     ret = gst_buffer_create_sub (buf, 0, GST_BUFFER_SIZE (buf));
       
   506 
       
   507     gst_buffer_unref (buf);
       
   508   }
       
   509 
       
   510   return ret;
       
   511 }
       
   512 
       
   513 typedef struct _GstSubBuffer GstSubBuffer;
       
   514 typedef struct _GstSubBufferClass GstSubBufferClass;
       
   515 
       
   516 #define GST_IS_SUBBUFFER(obj)   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), _gst_subbuffer_type))
       
   517 #define GST_SUBBUFFER_CAST(obj) ((GstSubBuffer *)(obj))
       
   518 
       
   519 struct _GstSubBuffer
       
   520 {
       
   521   GstBuffer buffer;
       
   522 
       
   523   GstBuffer *parent;
       
   524 };
       
   525 
       
   526 struct _GstSubBufferClass
       
   527 {
       
   528   GstBufferClass buffer_class;
       
   529 };
       
   530 
       
   531 static GstBufferClass *sub_parent_class;
       
   532 
       
   533 static void gst_subbuffer_init (GTypeInstance * instance, gpointer g_class);
       
   534 static void gst_subbuffer_class_init (gpointer g_class, gpointer class_data);
       
   535 static void gst_subbuffer_finalize (GstSubBuffer * buffer);
       
   536 
       
   537 static GType
       
   538 gst_subbuffer_get_type (void)
       
   539 {
       
   540   if (G_UNLIKELY (_gst_subbuffer_type == 0)) {
       
   541     static const GTypeInfo subbuffer_info = {
       
   542       sizeof (GstSubBufferClass),
       
   543       NULL,
       
   544       NULL,
       
   545       gst_subbuffer_class_init,
       
   546       NULL,
       
   547       NULL,
       
   548       sizeof (GstSubBuffer),
       
   549       0,
       
   550       gst_subbuffer_init,
       
   551       NULL
       
   552     };
       
   553 
       
   554     _gst_subbuffer_type = g_type_register_static (GST_TYPE_BUFFER,
       
   555         "GstSubBuffer", &subbuffer_info, 0);
       
   556   }
       
   557   return _gst_subbuffer_type;
       
   558 }
       
   559 
       
   560 static void
       
   561 gst_subbuffer_class_init (gpointer g_class, gpointer class_data)
       
   562 {
       
   563   GstBufferClass *buffer_class = GST_BUFFER_CLASS (g_class);
       
   564 
       
   565   sub_parent_class = g_type_class_peek_parent (g_class);
       
   566 
       
   567   buffer_class->mini_object_class.finalize =
       
   568       (GstMiniObjectFinalizeFunction) gst_subbuffer_finalize;
       
   569 }
       
   570 
       
   571 static void
       
   572 gst_subbuffer_finalize (GstSubBuffer * buffer)
       
   573 {
       
   574   gst_buffer_unref (buffer->parent);
       
   575 
       
   576   GST_MINI_OBJECT_CLASS (sub_parent_class)->
       
   577       finalize (GST_MINI_OBJECT_CAST (buffer));
       
   578 }
       
   579 
       
   580 static void
       
   581 gst_subbuffer_init (GTypeInstance * instance, gpointer g_class)
       
   582 {
       
   583   GST_BUFFER_FLAG_SET (GST_BUFFER_CAST (instance), GST_BUFFER_FLAG_READONLY);
       
   584 }
       
   585 
       
   586 /**
       
   587  * gst_buffer_create_sub:
       
   588  * @parent: a #GstBuffer.
       
   589  * @offset: the offset into parent #GstBuffer at which the new sub-buffer 
       
   590  *          begins.
       
   591  * @size: the size of the new #GstBuffer sub-buffer, in bytes.
       
   592  *
       
   593  * Creates a sub-buffer from @parent at @offset and @size.
       
   594  * This sub-buffer uses the actual memory space of the parent buffer.
       
   595  * This function will copy the offset and timestamp fields when the
       
   596  * offset is 0. If not, they will be set to #GST_CLOCK_TIME_NONE and 
       
   597  * #GST_BUFFER_OFFSET_NONE.
       
   598  * If @offset equals 0 and @size equals the total size of @buffer, the
       
   599  * duration and offset end fields are also copied. If not they will be set
       
   600  * to #GST_CLOCK_TIME_NONE and #GST_BUFFER_OFFSET_NONE.
       
   601  *
       
   602  * MT safe.
       
   603  * Returns: the new #GstBuffer.
       
   604  * Returns NULL if the arguments were invalid.
       
   605  */
       
   606 #ifdef __SYMBIAN32__
       
   607 EXPORT_C
       
   608 #endif
       
   609 
       
   610 GstBuffer *
       
   611 gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size)
       
   612 {
       
   613   GstSubBuffer *subbuffer;
       
   614   GstBuffer *parent;
       
   615   gboolean complete;
       
   616 
       
   617   g_return_val_if_fail (buffer != NULL, NULL);
       
   618   g_return_val_if_fail (buffer->mini_object.refcount > 0, NULL);
       
   619   g_return_val_if_fail (buffer->size >= offset + size, NULL);
       
   620 
       
   621   /* find real parent */
       
   622   if (GST_IS_SUBBUFFER (buffer)) {
       
   623     parent = GST_SUBBUFFER_CAST (buffer)->parent;
       
   624   } else {
       
   625     parent = buffer;
       
   626   }
       
   627   gst_buffer_ref (parent);
       
   628 
       
   629   /* create the new buffer */
       
   630   subbuffer = (GstSubBuffer *) gst_mini_object_new (_gst_subbuffer_type);
       
   631   subbuffer->parent = parent;
       
   632 
       
   633   GST_CAT_LOG (GST_CAT_BUFFER, "new subbuffer %p (parent %p)", subbuffer,
       
   634       parent);
       
   635 
       
   636   /* set the right values in the child */
       
   637   GST_BUFFER_DATA (GST_BUFFER_CAST (subbuffer)) = buffer->data + offset;
       
   638   GST_BUFFER_SIZE (GST_BUFFER_CAST (subbuffer)) = size;
       
   639 
       
   640   if ((offset == 0) && (size == GST_BUFFER_SIZE (buffer))) {
       
   641     /* copy all the flags except IN_CAPS */
       
   642     GST_BUFFER_FLAG_SET (subbuffer, GST_BUFFER_FLAGS (buffer));
       
   643     GST_BUFFER_FLAG_UNSET (subbuffer, GST_BUFFER_FLAG_IN_CAPS);
       
   644   } else {
       
   645     /* copy only PREROLL & GAP flags */
       
   646     GST_BUFFER_FLAG_SET (subbuffer, (GST_BUFFER_FLAGS (buffer) &
       
   647             (GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_GAP)));
       
   648   }
       
   649 
       
   650   /* we can copy the timestamp and offset if the new buffer starts at
       
   651    * offset 0 */
       
   652   if (offset == 0) {
       
   653     GST_BUFFER_TIMESTAMP (subbuffer) = GST_BUFFER_TIMESTAMP (buffer);
       
   654     GST_BUFFER_OFFSET (subbuffer) = GST_BUFFER_OFFSET (buffer);
       
   655     complete = (buffer->size == size);
       
   656   } else {
       
   657     GST_BUFFER_TIMESTAMP (subbuffer) = GST_CLOCK_TIME_NONE;
       
   658     GST_BUFFER_OFFSET (subbuffer) = GST_BUFFER_OFFSET_NONE;
       
   659     complete = FALSE;
       
   660   }
       
   661 
       
   662   if (complete) {
       
   663     GstCaps *caps;
       
   664 
       
   665     /* if we copied the complete buffer we can copy the duration,
       
   666      * offset_end and caps as well */
       
   667     GST_BUFFER_DURATION (subbuffer) = GST_BUFFER_DURATION (buffer);
       
   668     GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_END (buffer);
       
   669     if ((caps = GST_BUFFER_CAPS (buffer)))
       
   670       gst_caps_ref (caps);
       
   671     GST_BUFFER_CAPS (subbuffer) = caps;
       
   672   } else {
       
   673     GST_BUFFER_DURATION (subbuffer) = GST_CLOCK_TIME_NONE;
       
   674     GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_NONE;
       
   675     GST_BUFFER_CAPS (subbuffer) = NULL;
       
   676   }
       
   677   return GST_BUFFER_CAST (subbuffer);
       
   678 }
       
   679 
       
   680 /**
       
   681  * gst_buffer_is_span_fast:
       
   682  * @buf1: the first #GstBuffer.
       
   683  * @buf2: the second #GstBuffer.
       
   684  *
       
   685  * Determines whether a gst_buffer_span() can be done without copying
       
   686  * the contents, that is, whether the data areas are contiguous sub-buffers of 
       
   687  * the same buffer.
       
   688  *
       
   689  * MT safe.
       
   690  * Returns: TRUE if the buffers are contiguous,
       
   691  * FALSE if a copy would be required.
       
   692  */
       
   693 #ifdef __SYMBIAN32__
       
   694 EXPORT_C
       
   695 #endif
       
   696 
       
   697 gboolean
       
   698 gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2)
       
   699 {
       
   700   g_return_val_if_fail (buf1 != NULL && buf2 != NULL, FALSE);
       
   701   g_return_val_if_fail (buf1->mini_object.refcount > 0, FALSE);
       
   702   g_return_val_if_fail (buf2->mini_object.refcount > 0, FALSE);
       
   703 
       
   704   /* it's only fast if we have subbuffers of the same parent */
       
   705   return (GST_IS_SUBBUFFER (buf1) &&
       
   706       GST_IS_SUBBUFFER (buf2) &&
       
   707       (GST_SUBBUFFER_CAST (buf1)->parent == GST_SUBBUFFER_CAST (buf2)->parent)
       
   708       && ((buf1->data + buf1->size) == buf2->data));
       
   709 }
       
   710 
       
   711 /**
       
   712  * gst_buffer_span:
       
   713  * @buf1: the first source #GstBuffer to merge.
       
   714  * @offset: the offset in the first buffer from where the new
       
   715  * buffer should start.
       
   716  * @buf2: the second source #GstBuffer to merge.
       
   717  * @len: the total length of the new buffer.
       
   718  *
       
   719  * Creates a new buffer that consists of part of buf1 and buf2.
       
   720  * Logically, buf1 and buf2 are concatenated into a single larger
       
   721  * buffer, and a new buffer is created at the given offset inside
       
   722  * this space, with a given length.
       
   723  *
       
   724  * If the two source buffers are children of the same larger buffer,
       
   725  * and are contiguous, the new buffer will be a child of the shared
       
   726  * parent, and thus no copying is necessary. you can use
       
   727  * gst_buffer_is_span_fast() to determine if a memcpy will be needed.
       
   728  *
       
   729  * MT safe.
       
   730  * Returns: the new #GstBuffer that spans the two source buffers.
       
   731  * Returns NULL if the arguments are invalid.
       
   732  */
       
   733 #ifdef __SYMBIAN32__
       
   734 EXPORT_C
       
   735 #endif
       
   736 
       
   737 GstBuffer *
       
   738 gst_buffer_span (GstBuffer * buf1, guint32 offset, GstBuffer * buf2,
       
   739     guint32 len)
       
   740 {
       
   741   GstBuffer *newbuf;
       
   742 
       
   743   g_return_val_if_fail (buf1 != NULL && buf2 != NULL, NULL);
       
   744   g_return_val_if_fail (buf1->mini_object.refcount > 0, NULL);
       
   745   g_return_val_if_fail (buf2->mini_object.refcount > 0, NULL);
       
   746   g_return_val_if_fail (len > 0, NULL);
       
   747   g_return_val_if_fail (len <= buf1->size + buf2->size - offset, NULL);
       
   748 
       
   749   /* if the two buffers have the same parent and are adjacent */
       
   750   if (gst_buffer_is_span_fast (buf1, buf2)) {
       
   751     GstBuffer *parent = GST_SUBBUFFER_CAST (buf1)->parent;
       
   752 
       
   753     /* we simply create a subbuffer of the common parent */
       
   754     newbuf = gst_buffer_create_sub (parent,
       
   755         buf1->data - parent->data + offset, len);
       
   756   } else {
       
   757     GST_CAT_DEBUG (GST_CAT_BUFFER,
       
   758         "slow path taken while spanning buffers %p and %p", buf1, buf2);
       
   759     /* otherwise we simply have to brute-force copy the buffers */
       
   760     newbuf = gst_buffer_new_and_alloc (len);
       
   761 
       
   762     /* copy the first buffer's data across */
       
   763     memcpy (newbuf->data, buf1->data + offset, buf1->size - offset);
       
   764     /* copy the second buffer's data across */
       
   765     memcpy (newbuf->data + (buf1->size - offset), buf2->data,
       
   766         len - (buf1->size - offset));
       
   767   }
       
   768   /* if the offset is 0, the new buffer has the same timestamp as buf1 */
       
   769   if (offset == 0) {
       
   770     GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET (buf1);
       
   771     GST_BUFFER_TIMESTAMP (newbuf) = GST_BUFFER_TIMESTAMP (buf1);
       
   772 
       
   773     /* if we completely merged the two buffers (appended), we can
       
   774      * calculate the duration too. Also make sure we's not messing with
       
   775      * invalid DURATIONS */
       
   776     if (buf1->size + buf2->size == len) {
       
   777       if (GST_BUFFER_DURATION_IS_VALID (buf1) &&
       
   778           GST_BUFFER_DURATION_IS_VALID (buf2)) {
       
   779         /* add duration */
       
   780         GST_BUFFER_DURATION (newbuf) = GST_BUFFER_DURATION (buf1) +
       
   781             GST_BUFFER_DURATION (buf2);
       
   782       }
       
   783       if (GST_BUFFER_OFFSET_END_IS_VALID (buf2)) {
       
   784         /* add offset_end */
       
   785         GST_BUFFER_OFFSET_END (newbuf) = GST_BUFFER_OFFSET_END (buf2);
       
   786       }
       
   787     }
       
   788   }
       
   789 
       
   790   return newbuf;
       
   791 }