and size can be changed.
</para>
<para>
- Data access to the memory wrapped by the <classname>GstMemory</classname>
- object is always protected with a <function>gst_memory_map()</function>
- and <function>gst_memory_unmap()</function> pair. An access mode
- (read/write) must be given when mapping memory. The map
- function returns a pointer to the valid memory region that can
- then be accessed according to the requested access mode.
- </para>
- <para>
<classname>GstMemory</classname> objects are created by a
<classname>GstAllocator</classname> object. To implement support
for a new kind of memory type, you must implement a new allocator
object.
</para>
+ <sect2 id="section-allocation-memory-ex" xreflabel="GstMemory-ex">
+ <title>GstMemory API example</title>
+ <para>
+ Data access to the memory wrapped by the <classname>GstMemory</classname>
+ object is always protected with a <function>gst_memory_map()</function>
+ and <function>gst_memory_unmap()</function> pair. An access mode
+ (read/write) must be given when mapping memory. The map
+ function returns a pointer to the valid memory region that can
+ then be accessed according to the requested access mode.
+ </para>
+ <para>
+ Below is an example of making a <classname>GstMemory</classname>
+ object and using the <function>gst_memory_map()</function> to
+ access the memory region.
+ </para>
+ <programlisting>
+<![CDATA[
+[...]
+
+ GstMemory *mem;
+ GstMapInfo info;
+ gint i;
+
+ /* allocate 100 bytes */
+ mem = gst_allocator_alloc (NULL, 100, NULL);
+
+ /* get access to the memory in write mode */
+ gst_memory_map (mem, &info, GST_MAP_WRITE);
+
+ /* fill with pattern */
+ for (i = 0; i < info.size; i++)
+ info.data[i] = i;
+
+ /* release memory */
+ gst_memory_unmap (mem, &info);
+
+[...]
+]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="section-allocation-allocator" xreflabel="GstAllocator">
+ <title>Implementing a GstAllocator</title>
+ <para>
+ WRITEME
+ </para>
+ </sect2>
+
</sect1>
<sect1 id="section-allocation-buffer" xreflabel="GstBuffer">
</para>
</listitem>
</itemizedlist>
- <para>
- A buffer is writable when the refcount of the object is exactly 1, meaning
- that only one object is holding a ref to the buffer. You can only
- modify anything in the buffer when the buffer is writable. This means
- that you need to call <function>gst_buffer_make_writable()</function>
- before changing the timestamps, offsets, metadata or adding and
- removing memory blocks.
- </para>
+
+ <sect2 id="section-allocation-writability" xreflabel="GstBuffer-write">
+ <title>GstBuffer writability</title>
+ <para>
+ A buffer is writable when the refcount of the object is exactly 1, meaning
+ that only one object is holding a ref to the buffer. You can only
+ modify anything in the buffer when the buffer is writable. This means
+ that you need to call <function>gst_buffer_make_writable()</function>
+ before changing the timestamps, offsets, metadata or adding and
+ removing memory blocks.
+ </para>
+ </sect2>
+ <sect2 id="section-allocation-buffer-ex" xreflabel="GstBuffer-ex">
+ <title>GstBuffer API examples</title>
+ <para>
+ You can create a buffer with <function>gst_buffer_new ()</function>
+ and then add memory objects to it or you can use a convenience function
+ <function>gst_buffer_new_allocate ()</function> which combines the
+ two. It's also possible to wrap existing memory with
+ <function>gst_buffer_new_wrapped_full () </function> where you can
+ give the function to call when the memory should be freed.
+ </para>
+ <para>
+ You can access the memory of the buffer by getting and mapping the
+ <classname>GstMemory</classname> objects individually or by using
+ <function>gst_buffer_map ()</function>. The latter merges all the
+ memory into one big block and then gives you a pointer to this block.
+ </para>
+ <para>
+ Below is an example of how to create a buffer and access its memory.
+ </para>
+ <programlisting>
+<![CDATA[
+[...]
+ GstBuffer *buffer;
+ GstMemory *mem;
+ GstMapInfo info;
+
+ /* make empty buffer */
+ buffer = gst_buffer_new ();
+
+ /* make memory holding 100 bytes */
+ mem = gst_allocator_alloc (NULL, 100, NULL);
+
+ /* add the the buffer */
+ gst_buffer_append_memory (buffer, mem);
+
+[...]
+
+ /* get WRITE access to the memory and fill with 0xff */
+ gst_buffer_map (buffer, &info, GST_MAP_WRITE);
+ memset (info.data, 0xff, info.size);
+ gst_buffer_unmap (buffer, &info);
+
+[...]
+
+ /* free the buffer */
+ gst_buffer_unref (buffer);
+
+[...]
+]]>
+ </programlisting>
+ </sect2>
</sect1>
<sect1 id="section-allocation-meta" xreflabel="GstMeta">
backing up the memory of the buffer. This makes it easier for elements
to locate the X image from the buffer.
</para>
+ <para>
+ The metadata system separates API specification (what the metadata
+ and its API look like) and the implementation (how it works). This makes
+ it possible to make different implementations of the same API,
+ for example, depending on the hardware you are running on.
+ </para>
+
+ <sect2 id="section-allocation-meta-ex" xreflabel="GstMeta-ex">
+ <title>GstMeta API example</title>
+ <para>
+ After allocating a new buffer, you can add metadata to the buffer
+ with the metadata specific API. This means that you will need to
+ link to the header file where the metadata is defined to use
+ its API.
+ </para>
+ <para>
+ By convention, a metadata API with name <classname>FooBar</classname>
+ should provide two methods, a
+ <function>gst_buffer_add_foo_bar_meta ()</function> and a
+ <function>gst_buffer_get_foo_bar_meta ()</function>. Both functions
+ should return a pointer to a <classname>FooBarMeta</classname>
+ structure that contains the metadata fields. Some of the
+ <function>_add_*_meta ()</function> can have extra parameters that
+ will usually be used to configure the metadata structure for you.
+ </para>
+ <para>
+ Let's have a look at the metadata that is used to specify a cropping
+ region for video frames.
+ </para>
+ <programlisting>
+<![CDATA[
+#include <gst/video/gstvideometa.h>
+
+[...]
+ GstVideoCropMeta *meta;
+
+ /* buffer points to a video frame, add some cropping metadata */
+ meta = gst_buffer_add_video_crop_meta (buffer);
+
+ /* configure the cropping metadata */
+ meta->x = 8;
+ meta->y = 8;
+ meta->width = 120;
+ meta->height = 80;
+[...]
+]]>
+ </programlisting>
+ <para>
+ An element can then use the metadata on the buffer when rendering
+ the frame like this:
+ </para>
+ <programlisting>
+<![CDATA[
+#include <gst/video/gstvideometa.h>
+
+[...]
+ GstVideoCropMeta *meta;
+
+ /* buffer points to a video frame, get the cropping metadata */
+ meta = gst_buffer_get_video_crop_meta (buffer);
+
+ if (meta) {
+ /* render frame with cropping */
+ _render_frame_cropped (buffer, meta->x, meta->y, meta->width, meta->height);
+ } else {
+ /* render frame */
+ _render_frame (buffer);
+ }
+[...]
+
+]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="section-allocation-meta-new" xreflabel="GstMeta-new">
+ <title>Implementing new GstMeta</title>
+ <para>
+ In the next sections we show how you can add new metadata to the
+ system and use it on buffers.
+ </para>
+
+ <sect3 id="section-allocation-meta-api" xreflabel="GstMeta-api">
+ <title>Define the metadata API</title>
+ <para>
+ First we need to define what our API will look like and we
+ will have to register this API to the system. This is important
+ because this API definition will be used when elements negotiate
+ what kind of metadata they will exchange. The API definition
+ also contains arbitrary tags that give hints about what the
+ metadata contains. This is important when we see how metadata
+ is preserved when buffers pass through the pipeline.
+ </para>
+ <para>
+ If you are making a new implementation of an existing API,
+ you can skip this step and move on to the implementation step.
+ </para>
+ <para>
+ First we start with making the
+ <filename>my-example-meta.h</filename> header file that will contain
+ the definition of the API and structure for our metadata.
+ </para>
+ <programlisting>
+<![CDATA[
+#include <gst/gst.h>
+
+typedef struct _MyExampleMeta MyExampleMeta;
+
+struct _MyExampleMeta {
+ GstMeta meta;
+
+ gint age;
+ gchar *name;
+};
+
+GType my_example_meta_api_get_type (void);
+#define MY_EXAMPLE_META_API_TYPE (my_example_meta_api_get_type())
+
+#define gst_buffer_get_my_example_meta(b) \
+ ((MyExampleMeta*)gst_buffer_get_meta((b),MY_EXAMPLE_META_API_TYPE))
+]]>
+ </programlisting>
+ <para>
+ The metadata API definition consists of the definition of the
+ structure that holds a gint and a string. The first field in
+ the structure must be <classname>GstMeta</classname>.
+ </para>
+ <para>
+ We also define a <function>my_example_meta_api_get_type ()</function>
+ function that will register out metadata API definition. We
+ also define a convenience macro
+ <function>gst_buffer_get_my_example_meta ()</function> that simply
+ finds and returns the metadata with our new API.
+ </para>
+ <para>
+ Next let's have a look at how the
+ <function>my_example_meta_api_get_type ()</function> function is
+ implemented in the <filename>my-example-meta.c</filename> file.
+ </para>
+ <programlisting>
+<![CDATA[
+#include "my-example-meta.h"
+
+GType
+my_example_meta_api_get_type (void)
+{
+ static volatile GType type;
+ static const gchar *tags[] = { "foo", "bar", NULL };
+
+ if (g_once_init_enter (&type)) {
+ GType _type = gst_meta_api_type_register ("MyExampleMetaAPI", tags);
+ g_once_init_leave (&type, _type);
+ }
+ return type;
+}
+]]>
+ </programlisting>
+ <para>
+ As you can see, it simply uses the
+ <function>gst_meta_api_type_register ()</function> function to
+ register a name for the api and some tags. The result is a
+ new pointer GType that defines the newly registered API.
+ </para>
+ </sect3>
+
+ <sect3 id="section-allocation-meta-impl" xreflabel="GstMeta-impl">
+ <title>Implementing a metadata API</title>
+ <para>
+ Next we can make an implementation for a registered metadata
+ API GType. The implementation detail of a metadata API
+ are kept in a <classname>GstMetaInfo</classname> structure
+ that you will make available to the users of your metadata
+ API implementation with a <function>my_example_meta_get_info ()</function>
+ function and a convenience <function>MY_EXAMPLE_META_INFO</function>
+ macro. You will also make a method to add your metadata
+ implementation to a <classname>GstBuffer</classname>.
+ Your <filename>my-example-meta.h</filename> header file will
+ need thse additions:
+ </para>
+ <programlisting>
+<![CDATA[
+[...]
+
+/* implementation */
+const GstMetaInfo *my_example_meta_get_info (void);
+#define MY_EXAMPLE_META_INFO (my_example_meta_get_info())
+
+MyExampleMeta * gst_buffer_add_my_example_meta (GstBuffer *buffer,
+ gint age,
+ const gchar *name);
+]]>
+ </programlisting>
+ <para>
+ Let's have a look at how these functions are
+ implemented in the <filename>my-example-meta.c</filename> file.
+ </para>
+ <programlisting>
+<![CDATA[
+[...]
+
+static gboolean
+my_example_meta_init (GstMeta * meta, gpointer params, GstBuffer * buffer)
+{
+ MyExampleMeta *emeta = (MyExampleMeta *) meta;
+
+ emeta->age = 0;
+ emeta->name = NULL;
+
+ return TRUE;
+}
+
+static gboolean
+my_example_meta_transform (GstBuffer * transbuf, GstMeta * meta,
+ GstBuffer * buffer, GQuark type, gpointer data)
+{
+ MyExampleMeta *emeta = (MyExampleMeta *) meta;
+
+ /* we always copy no matter what transform */
+ gst_buffer_add_my_example_meta (transbuf, emeta->age, emeta->name);
+
+ return TRUE;
+}
+
+static void
+my_example_meta_free (GstMeta * meta, GstBuffer * buffer)
+{
+ MyExampleMeta *emeta = (MyExampleMeta *) meta;
+
+ g_free (emeta->name)
+ emeta->name = NULL;
+}
+
+const GstMetaInfo *
+my_example_meta_get_info (void)
+{
+ static const GstMetaInfo *meta_info = NULL;
+
+ if (meta_info == NULL) {
+ meta_info = gst_meta_register (MY_EXAMPLE_META_API_TYPE,
+ "MyExampleMeta",
+ sizeof (MyExampleMeta),
+ my_example_meta_init,
+ my_example_meta_free,
+ my_example_meta_transform);
+ }
+ return meta_info;
+}
+
+MyExampleMeta *
+gst_buffer_add_my_example_meta (GstBuffer *buffer,
+ gint age,
+ const gchar *name)
+{
+ MyExampleMeta *meta;
+
+ g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
+
+ meta = (MyExampleMeta *) gst_buffer_add_meta (buffer,
+ MY_EXAMPLE_META_INFO, NULL);
+
+ meta->age = age;
+ meta->name = g_strdup (name);
+
+ return meta;
+}
+]]>
+ </programlisting>
+ <para>
+ <function>gst_meta_register ()</function> registers the implementation
+ details, like the API that you implement and the size of the
+ metadata structure along with methods to initialize and free the
+ memory area. You can also implement a transform function that will
+ be called when a certain transformation (identified by the quark and
+ quark specific data) is performed on a buffer.
+ </para>
+ <para>
+ Lastly, you implement a <function>gst_buffer_add_*_meta()</function>
+ that adds the metadata implementation to a buffer and sets the
+ values of the metadata.
+ </para>
+ </sect3>
+ </sect2>
+
</sect1>
<sect1 id="section-allocation-bufferpool" xreflabel="GstBufferPool">
to the buffers in the pool or such as enabling specific padding on
the memory in the buffers.
</para>
+
+ <sect2 id="section-allocation-pool-ex" xreflabel="GstBufferPool-ex">
+ <title>GstBufferPool API example</title>
+ <para>
+ WRITEME
+ </para>
+ </sect2>
+
+ <sect2 id="section-allocation-pool-new" xreflabel="GstBufferPool-new">
+ <title>Implementing a new GstBufferPool</title>
+ <para>
+ WRITEME
+ </para>
+ </sect2>
+
</sect1>
<sect1 id="section-allocation-query" xreflabel="GST_QUERY_ALLOCATION">
from the available bufferpools, allocators and metadata how it will
allocate buffers.
</para>
- <para>
- In many baseclasses you will see the following virtual methods for
- influencing the allocation strategy:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <function>propose_allocation ()</function> should suggest
- allocation parameters for the upstream element.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>decide_allocation ()</function> should decide the
- allocation parameters from the suggestions received from
- downstream.
- </para>
- </listitem>
- </itemizedlist>
+
+ <sect2 id="section-allocation-query-ex" xreflabel="Allocation-ex">
+ <title>ALLOCATION query example</title>
+ <para>
+ WRITEME
+ </para>
+ </sect2>
+
+ <sect2 id="section-allocation-query-base" xreflabel="Allocation-base">
+ <title>The ALLOCATION query in base classes</title>
+ <para>
+ In many baseclasses you will see the following virtual methods for
+ influencing the allocation strategy:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <function>propose_allocation ()</function> should suggest
+ allocation parameters for the upstream element.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <function>decide_allocation ()</function> should decide the
+ allocation parameters from the suggestions received from
+ downstream.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
</sect1>
</chapter>