mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			1035 lines
		
	
	
	
		
			38 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			1035 lines
		
	
	
	
		
			38 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
/** \page page_spa_pod SPA POD
 | 
						|
 | 
						|
\ref spa_pod (plain old data) is a sort of data container. It is comparable to
 | 
						|
DBus Variant or LV2 Atom.
 | 
						|
 | 
						|
A POD can express nested structures of objects (with properties), vectors,
 | 
						|
arrays, sequences and various primitives types. All information in the POD
 | 
						|
is laid out sequentially in memory and can be written directly to
 | 
						|
storage or exchanged between processes or threads without additional
 | 
						|
marshalling.
 | 
						|
 | 
						|
Each POD is made of a 32 bits size followed by a 32 bits type field,
 | 
						|
followed by the POD contents. This makes it possible to skip over unknown
 | 
						|
POD types. The POD start is always aligned to 8 bytes.
 | 
						|
 | 
						|
POD's can be efficiently constructed and parsed in real-time threads without
 | 
						|
requiring memory allocations.
 | 
						|
 | 
						|
POD's use the SPA type system for the basic types and containers. See
 | 
						|
the SPA types for more info.
 | 
						|
 | 
						|
 | 
						|
# Types
 | 
						|
 | 
						|
POD's can contain a number of basic SPA types:
 | 
						|
 | 
						|
- `SPA_TYPE_None`: No value or a NULL pointer.
 | 
						|
- `SPA_TYPE_Bool`: A boolean value.
 | 
						|
- `SPA_TYPE_Id`: An enumerated value.
 | 
						|
- `SPA_TYPE_Int`, `SPA_TYPE_Long`, `SPA_TYPE_Float`, `SPA_TYPE_Double`:
 | 
						|
  various numeral types, 32 and 64 bits.
 | 
						|
- `SPA_TYPE_String`: A string.
 | 
						|
- `SPA_TYPE_Bytes`: A byte array.
 | 
						|
- `SPA_TYPE_Rectangle`: A rectangle with width and height.
 | 
						|
- `SPA_TYPE_Fraction`: A fraction with numerator and denominator.
 | 
						|
- `SPA_TYPE_Bitmap`: An array of bits.
 | 
						|
 | 
						|
POD's can be grouped together in these container types:
 | 
						|
 | 
						|
- `SPA_TYPE_Array`: An array of equal sized objects.
 | 
						|
- `SPA_TYPE_Struct`: A collection of types and objects.
 | 
						|
- `SPA_TYPE_Object`: An object with properties.
 | 
						|
- `SPA_TYPE_Sequence`: A timed sequence of POD's.
 | 
						|
 | 
						|
POD's can also contain some extra types:
 | 
						|
 | 
						|
- `SPA_TYPE_Pointer`: A typed pointer in memory.
 | 
						|
- `SPA_TYPE_Fd`: A file descriptor.
 | 
						|
- `SPA_TYPE_Choice`: A choice of values.
 | 
						|
- `SPA_TYPE_Pod`: A generic type for the POD itself.
 | 
						|
 | 
						|
 | 
						|
# Constructing A POD
 | 
						|
 | 
						|
A POD is usually constructed with a `struct spa_pod_builder`. The builder
 | 
						|
needs to be initialized with a memory region to write into. It is
 | 
						|
also possible to dynamically grow the memory as needed.
 | 
						|
 | 
						|
The most common way to construct a POD is on the stack. This does
 | 
						|
not require any memory allocations. The size of the POD can be
 | 
						|
estimated pretty easily and if the buffer is not large enough, an
 | 
						|
appropriate error will be generated.
 | 
						|
 | 
						|
The code fragment below initializes a POD builder to write into
 | 
						|
the stack allocated buffer.
 | 
						|
 | 
						|
\code{.c}
 | 
						|
uint8_t buffer[4096];
 | 
						|
struct spa_pod_builder b;
 | 
						|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
 | 
						|
\endcode
 | 
						|
 | 
						|
Next we need to write some object into the builder. Let's write
 | 
						|
a simple struct with an Int and Float in it. Structs are comparable
 | 
						|
to JSON arrays.
 | 
						|
 | 
						|
\code{.c}
 | 
						|
struct spa_pod_frame f;
 | 
						|
spa_pod_builder_push_struct(&b, &f);
 | 
						|
\endcode
 | 
						|
 | 
						|
First we open the struct container, the `struct spa_pod_frame` keeps
 | 
						|
track of the container context. Next we add some values to
 | 
						|
the container like this:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
spa_pod_builder_int(&b, 5);
 | 
						|
spa_pod_builder_float(&b, 3.1415f);
 | 
						|
\endcode
 | 
						|
 | 
						|
Then we close the container by popping the frame again:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
struct spa_pod *pod;
 | 
						|
pod = spa_pod_builder_pop(&b, &f);
 | 
						|
\endcode
 | 
						|
 | 
						|
`spa_pod_builder_pop()` returns a reference to the object we completed
 | 
						|
on the stack.
 | 
						|
 | 
						|
## Using varargs Builder
 | 
						|
 | 
						|
We can also use the following construct to make POD objects:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
spa_pod_builder_push_struct(&b, &f);
 | 
						|
spa_pod_builder_add(&b,
 | 
						|
	SPA_POD_Int(5),
 | 
						|
	SPA_POD_Float(3.1415f));
 | 
						|
pod = spa_pod_builder_pop(&b, &f);
 | 
						|
\endcode
 | 
						|
 | 
						|
Or even shorter:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
pod = spa_pod_builder_add_struct(&b,
 | 
						|
	SPA_POD_Int(5),
 | 
						|
	SPA_POD_Float(3.1415f));
 | 
						|
\endcode
 | 
						|
 | 
						|
It's not possible to use the varargs builder to make a sequence or
 | 
						|
array, use the normal builder methods for that.
 | 
						|
 | 
						|
## Making Objects
 | 
						|
 | 
						|
POD objects are containers for properties and are comparable to JSON
 | 
						|
objects.
 | 
						|
 | 
						|
Start by pushing an object:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
 | 
						|
\endcode
 | 
						|
 | 
						|
An object requires an object type (`SPA_TYPE_OBJECT_Props`) and a context
 | 
						|
ID (`SPA_PARAM_Props`). The object type defines the properties that can be
 | 
						|
added to the object and their meaning. The SPA type system allows you to
 | 
						|
make this connection (See the type system).
 | 
						|
 | 
						|
Next we can push some properties in the object:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
spa_pod_builder_prop(&b, SPA_PROP_device, 0);
 | 
						|
spa_pod_builder_string(&b, "hw:0");
 | 
						|
spa_pod_builder_prop(&b, SPA_PROP_frequency, 0);
 | 
						|
spa_pod_builder_float(&b, 440.0);
 | 
						|
\endcode
 | 
						|
 | 
						|
As can be seen, we always need to push a prop (with key and flags)
 | 
						|
and then the associated value. For performance reasons it is a good
 | 
						|
idea to always push (and parse) the object keys in ascending order.
 | 
						|
 | 
						|
Don't forget to pop the result when the object is finished:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
pod = spa_pod_builder_pop(&b, &f);
 | 
						|
\endcode
 | 
						|
 | 
						|
There is a shortcut for making objects:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
pod = spa_pod_builder_add_object(&b,
 | 
						|
	SPA_TYPE_OBJECT_Props, SPA_PARAM_Props,
 | 
						|
	SPA_PROP_device,    SPA_POD_String("hw:0"),
 | 
						|
	SPA_PROP_frequency, SPA_POD_Float(440.0f));
 | 
						|
\endcode
 | 
						|
 | 
						|
## Choice Values
 | 
						|
 | 
						|
It is possible to express ranges or enumerations of possible
 | 
						|
values for properties (and to some extend structs). This is achieved
 | 
						|
with choice values.
 | 
						|
 | 
						|
Choice values are really just a choice type and an array of choice values
 | 
						|
(of the same type). Depending on the choice type, the array values are
 | 
						|
interpreted in different ways:
 | 
						|
 | 
						|
- `SPA_CHOICE_None`: No choice, first value is current.
 | 
						|
- `SPA_CHOICE_Range`: Range: default, min, max.
 | 
						|
- `SPA_CHOICE_Step`: Range with step: default, min, max, step.
 | 
						|
- `SPA_CHOICE_Enum`: Enum: default, alternative,...
 | 
						|
- `SPA_CHOICE_Flags`: Bitmask of flags.
 | 
						|
 | 
						|
Let's illustrate this with a props object that specifies a range of
 | 
						|
possible values for the frequency:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
struct spa_pod_frame f2;
 | 
						|
 | 
						|
spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
 | 
						|
spa_pod_builder_prop(&b, SPA_PROP_frequency, 0);
 | 
						|
spa_pod_builder_push_choice(&b, &f2, SPA_CHOICE_Range, 0);
 | 
						|
spa_pod_builder_float(&b, 440.0);   //  default
 | 
						|
spa_pod_builder_float(&b, 110.0);   //  min
 | 
						|
spa_pod_builder_float(&b, 880.0);   //  min
 | 
						|
pod = spa_pod_builder_pop(&b, &f2);
 | 
						|
pod = spa_pod_builder_pop(&b, &f);
 | 
						|
\endcode
 | 
						|
 | 
						|
As you can see, first push the choice as a range, then the values. A range
 | 
						|
choice expects at least three values, the default value, minimum and maximum
 | 
						|
values. There is a shortcut for this as well using varargs:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
pod = spa_pod_builder_add_object(&b,
 | 
						|
	SPA_TYPE_OBJECT_Props, SPA_PARAM_Props,
 | 
						|
	SPA_PROP_frequency, SPA_POD_CHOICE_RANGE_Float(440.0f, 110.0f, 880.0f));
 | 
						|
\endcode
 | 
						|
 | 
						|
## Choice Examples
 | 
						|
 | 
						|
This is a description of a possible `SPA_TYPE_OBJECT_Format` as used when
 | 
						|
enumerating allowed formats (`SPA_PARAM_EnumFormat`) in SPA objects:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
pod = spa_pod_builder_add_object(&b,
 | 
						|
	SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
 | 
						|
	//  specify the media type and subtype
 | 
						|
	SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
 | 
						|
	SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
 | 
						|
	//  audio/raw properties
 | 
						|
	SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(4,  //  4 values follow
 | 
						|
					SPA_AUDIO_FORMAT_S16, //  default
 | 
						|
					SPA_AUDIO_FORMAT_S16, //  alternative1
 | 
						|
					SPA_AUDIO_FORMAT_S32, //  alternative2
 | 
						|
					SPA_AUDIO_FORMAT_F32  //  alternative3
 | 
						|
				   ),
 | 
						|
	SPA_FORMAT_AUDIO_rate,     SPA_POD_CHOICE_RANGE_Int(
 | 
						|
					44100,		//  default
 | 
						|
					8000,		//  min
 | 
						|
					192000		//  max
 | 
						|
				   ),
 | 
						|
	SPA_FORMAT_AUDIO_channels, SPA_POD_Int(2));
 | 
						|
\endcode
 | 
						|
 | 
						|
## Fixate
 | 
						|
 | 
						|
We can remove all choice values from the object with the
 | 
						|
`spa_pod_object_fixate()` method. This modifies the pod in-place and sets all
 | 
						|
choice properties to `SPA_CHOICE_None`, forcing the default value as the
 | 
						|
only available value in the choice.
 | 
						|
 | 
						|
Running fixate on our previous example would result in an object equivalent
 | 
						|
to:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
pod = spa_pod_builder_add_object(&b,
 | 
						|
	SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
 | 
						|
	//  specify the media type and subtype
 | 
						|
	SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
 | 
						|
	SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
 | 
						|
	//  audio/raw properties
 | 
						|
	SPA_FORMAT_AUDIO_format,   SPA_POD_Id(SPA_AUDIO_FORMAT_S16),
 | 
						|
	SPA_FORMAT_AUDIO_rate,     SPA_POD_Int(44100),
 | 
						|
	SPA_FORMAT_AUDIO_channels, SPA_POD_Int(2));
 | 
						|
\endcode
 | 
						|
 | 
						|
 | 
						|
# Parsing A POD
 | 
						|
 | 
						|
Parsing a POD usually consists of:
 | 
						|
 | 
						|
- Validating if raw bytes + size can contain a valid POD.
 | 
						|
- Inspecting the type of a POD.
 | 
						|
- Looping over the items in an object or struct.
 | 
						|
- Getting data out of POD's.
 | 
						|
 | 
						|
## Validating Bytes
 | 
						|
 | 
						|
Use `spa_pod_from_data()` to check if maxsize of bytes in data contain
 | 
						|
a POD at the size bytes starting at offset. This function checks that
 | 
						|
the POD size will fit and not overflow.
 | 
						|
 | 
						|
\code{.c}
 | 
						|
struct spa_pod *pod;
 | 
						|
pod = spa_pod_from_data(data, maxsize, offset, size);
 | 
						|
\endcode
 | 
						|
 | 
						|
## Checking The Type Of POD
 | 
						|
 | 
						|
Use one of `spa_pod_is_bool()`, `spa_pod_is_int()`, etc to check
 | 
						|
for the type of the pod. For simple (non-container) types,
 | 
						|
`spa_pod_get_bool()`, `spa_pod_get_int()` etc can be used to
 | 
						|
extract the value of the pod.
 | 
						|
 | 
						|
`spa_pod_is_object_type()` can be used to check if the POD contains
 | 
						|
an object of the expected type.
 | 
						|
 | 
						|
## Struct Fields
 | 
						|
 | 
						|
To iterate over the fields of a struct use:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
struct spa_pod *pod, *obj;
 | 
						|
SPA_POD_STRUCT_FOREACH(obj, pod) {
 | 
						|
	printf("field type:%d\n", pod->type);
 | 
						|
}
 | 
						|
\endcode
 | 
						|
 | 
						|
For parsing structs it is usually much easier to use the parser
 | 
						|
below.
 | 
						|
 | 
						|
## Object Properties
 | 
						|
 | 
						|
To iterate over the properties in an object you can do:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
struct spa_pod_prop *prop;
 | 
						|
struct spa_pod_object *obj = (struct spa_pod_object*)pod;
 | 
						|
SPA_POD_OBJECT_FOREACH(pod, prop) {
 | 
						|
	printf("prop key:%d\n", prop->key);
 | 
						|
}
 | 
						|
\endcode
 | 
						|
 | 
						|
There is a function to retrieve the property for a certain key
 | 
						|
in the object. If the properties of the object are in ascending
 | 
						|
order, you can start searching from the previous key.
 | 
						|
 | 
						|
\code{.c}
 | 
						|
struct spa_pod_prop *prop;
 | 
						|
prop = spa_pod_find_prop(obj, NULL, SPA_FORMAT_AUDIO_format);
 | 
						|
  //  .. use first prop
 | 
						|
prop = spa_pod_find_prop(obj, prop, SPA_FORMAT_AUDIO_rate);
 | 
						|
  //  .. use next prop
 | 
						|
\endcode
 | 
						|
 | 
						|
## Parser
 | 
						|
 | 
						|
Similar to the builder, there is a parser object as well.
 | 
						|
 | 
						|
If the fields in a struct are known, it is much easier to use the
 | 
						|
parser. Similarly, if the object type (and thus its keys) are known,
 | 
						|
the parser is easier.
 | 
						|
 | 
						|
First initialize a `struct spa_pod_parser`:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
struct spa_pod_parser p;
 | 
						|
spa_pod_parser_pod(&p, obj);
 | 
						|
\endcode
 | 
						|
 | 
						|
You can then enter containers such as objects or structs with a push
 | 
						|
operation:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
struct spa_pod_frame f;
 | 
						|
spa_pod_parser_push_struct(&p, &f);
 | 
						|
\endcode
 | 
						|
 | 
						|
You need to store the context in a `struct spa_pod_frame` to be able
 | 
						|
to exit the container again later.
 | 
						|
 | 
						|
You can then parse each field. The parser takes care of moving to the
 | 
						|
next field.
 | 
						|
 | 
						|
\code{.c}
 | 
						|
uint32_t id, val;
 | 
						|
spa_pod_parser_get_id(&p, &id);
 | 
						|
spa_pod_parser_get_int(&p, &val);
 | 
						|
...
 | 
						|
\endcode
 | 
						|
 | 
						|
And finally exit the container again:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
spa_pod_parser_pop(&p, &f);
 | 
						|
\endcode
 | 
						|
 | 
						|
## Parser With Variable Arguments
 | 
						|
 | 
						|
In most cases, parsing objects is easier with the variable argument
 | 
						|
functions. The parse function look like the mirror image of the builder
 | 
						|
functions.
 | 
						|
 | 
						|
To parse a struct:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
spa_pod_parser_get_struct(&p,
 | 
						|
	SPA_POD_Id(&id),
 | 
						|
	SPA_POD_Int(&val));
 | 
						|
\endcode
 | 
						|
 | 
						|
To parse properties in an object:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
uint32_t id, type, subtype, format, rate, channels;
 | 
						|
spa_pod_parser_get_object(&p,
 | 
						|
	SPA_TYPE_OBJECT_Format, &id,
 | 
						|
	SPA_FORMAT_mediaType,      SPA_POD_Id(&type),
 | 
						|
	SPA_FORMAT_mediaSubtype,   SPA_POD_Id(&subtype),
 | 
						|
	SPA_FORMAT_AUDIO_format,   SPA_POD_Id(&format),
 | 
						|
	SPA_FORMAT_AUDIO_rate,     SPA_POD_Int(&rate),
 | 
						|
	SPA_FORMAT_AUDIO_channels, SPA_POD_Int(&channels));
 | 
						|
\endcode
 | 
						|
 | 
						|
When parsing objects it is possible to have optional fields. You can
 | 
						|
make a field optional be parsing it with the `SPA_POD_OPT_` prefix
 | 
						|
for the type.
 | 
						|
 | 
						|
In the next example, the rate and channels fields are optional
 | 
						|
and when they are not present, the variables will not be changed.
 | 
						|
 | 
						|
\code{.c}
 | 
						|
uint32_t id, type, subtype, format, rate = 0, channels = 0;
 | 
						|
spa_pod_parser_get_object(&p,
 | 
						|
	SPA_TYPE_OBJECT_Format, &id,
 | 
						|
	SPA_FORMAT_mediaType,      SPA_POD_Id(&type),
 | 
						|
	SPA_FORMAT_mediaSubtype,   SPA_POD_Id(&subtype),
 | 
						|
	SPA_FORMAT_AUDIO_format,   SPA_POD_Id(&format),
 | 
						|
	SPA_FORMAT_AUDIO_rate,     SPA_POD_OPT_Int(&rate),
 | 
						|
	SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&channels));
 | 
						|
\endcode
 | 
						|
 | 
						|
It is not possible to parse a sequence or array with the parser.
 | 
						|
Use the iterator for this.
 | 
						|
 | 
						|
## Choice Values
 | 
						|
 | 
						|
The parser will handle choice values as long as they are of type
 | 
						|
`none`. It will then parse the single value from the choice. When
 | 
						|
dealing with other choice values, it's possible to parse the
 | 
						|
property values into a `struct spa_pod` and then inspect the choice
 | 
						|
manually, if needed.
 | 
						|
 | 
						|
Here is an example of parsing the format values as a POD:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
uint32_t id, type, subtype;
 | 
						|
struct spa_pod *format;
 | 
						|
spa_pod_parser_get_object(&p,
 | 
						|
	SPA_TYPE_OBJECT_Format, &id,
 | 
						|
	SPA_FORMAT_mediaType,      SPA_POD_Id(&type),
 | 
						|
	SPA_FORMAT_mediaSubtype,   SPA_POD_Id(&subtype),
 | 
						|
	SPA_FORMAT_AUDIO_format,   SPA_POD_Pod(&format));
 | 
						|
\endcode
 | 
						|
 | 
						|
`spa_pod_get_values()` is a useful function. It returns a
 | 
						|
`struct spa_pod*` with and array of values. For normal POD's
 | 
						|
and choice none values, it simply returns the POD and one value.
 | 
						|
For other choice values it returns the choice type and an array
 | 
						|
of values:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
struct spa_pod *value;
 | 
						|
uint32_t n_vals, choice;
 | 
						|
 | 
						|
value = spa_pod_get_values(pod, &n_vals, &choice);
 | 
						|
 | 
						|
switch (choice) {
 | 
						|
case SPA_CHOICE_None:
 | 
						|
        //  one single value
 | 
						|
	break;
 | 
						|
case SPA_CHOICE_Range:
 | 
						|
        // array of values of type of pod, cast to right type
 | 
						|
	// to iterate.
 | 
						|
	uint32_t *v = SPA_POD_BODY(values);
 | 
						|
	if (n_vals < 3)
 | 
						|
		break;
 | 
						|
	printf("default value: %u\n", v[0]);
 | 
						|
	printf("min value: %u\n", v[1]);
 | 
						|
	printf("max value: %u\n", v[2]);
 | 
						|
	break;
 | 
						|
 | 
						|
	//  ...
 | 
						|
default:
 | 
						|
	break;
 | 
						|
}
 | 
						|
\endcode
 | 
						|
 | 
						|
 | 
						|
# Filter
 | 
						|
 | 
						|
Given two POD objects of the same type (object, struct, ..) one can
 | 
						|
run a filter and generate a new POD that only contains values that
 | 
						|
are compatible with both input POD's.
 | 
						|
 | 
						|
This is, for example, used to find a compatible format between two ports.
 | 
						|
 | 
						|
As an example we can run a filter on two simple POD's:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
pod = spa_pod_builder_add_object(&b,
 | 
						|
	SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
 | 
						|
	SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
 | 
						|
	SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
 | 
						|
	SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(4,  //  4 values follow
 | 
						|
					SPA_AUDIO_FORMAT_S16, //  default
 | 
						|
					SPA_AUDIO_FORMAT_S16, //  alternative1
 | 
						|
					SPA_AUDIO_FORMAT_S32, //  alternative2
 | 
						|
					SPA_AUDIO_FORMAT_F32  //  alternative3
 | 
						|
				   ));
 | 
						|
 | 
						|
filter = spa_pod_builder_add_object(&b,
 | 
						|
	SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
 | 
						|
	SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
 | 
						|
	SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
 | 
						|
	SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(3,  //  3 values follow
 | 
						|
					SPA_AUDIO_FORMAT_S16, //  default
 | 
						|
					SPA_AUDIO_FORMAT_S16, //  alternative1
 | 
						|
					SPA_AUDIO_FORMAT_F64  //  alternative2
 | 
						|
				   ));
 | 
						|
 | 
						|
struct spa_pod *result;
 | 
						|
if (spa_pod_filter(&b, &result, pod, filter) < 0)
 | 
						|
	goto exit_error;
 | 
						|
\endcode
 | 
						|
 | 
						|
Filter will contain a POD equivalent to:
 | 
						|
 | 
						|
\code{.c}
 | 
						|
result = spa_pod_builder_add_object(&b,
 | 
						|
	SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
 | 
						|
	SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
 | 
						|
	SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
 | 
						|
	SPA_FORMAT_AUDIO_format,   SPA_AUDIO_FORMAT_S16);
 | 
						|
\endcode
 | 
						|
 | 
						|
# POD Layout
 | 
						|
 | 
						|
A POD always starts with a size/type pair of uint32_t in native endianness,
 | 
						|
followed by size in bytes of the payload data and padding. See
 | 
						|
\ref page_spa_pod for more details.
 | 
						|
 | 
						|
The payload is always padded to 8 bytes so that a complete pod is always
 | 
						|
a multiple of 8 bytes.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   size                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   type                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   payload ...                                                 |
 | 
						|
   .                                                |  ... padding .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
The total size of the POD is thus ROUND_UP_8(8 + size).
 | 
						|
 | 
						|
# POD Types
 | 
						|
 | 
						|
Here follows the layout of the POD types.
 | 
						|
 | 
						|
## None (1)
 | 
						|
 | 
						|
Type 1 is the None type or the null pointer. It has a size of 0 and thus
 | 
						|
no payload.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   0                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   1                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## Bool (2)
 | 
						|
 | 
						|
Type 2 is the Bool type. I contains a true or false value. The value is
 | 
						|
stored in a int32, a value of 0 is false, any other value is true.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   4                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   2                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   value (int32)                                               |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   padding                                                     |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## Id (3)
 | 
						|
 | 
						|
An id is stored as a uint32. The id refers to an index in a table where more
 | 
						|
information about the value can be found. This is typically a type table
 | 
						|
containing some well known ids.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   4                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   3                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   id (uint32)                                                 |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   padding                                                     |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## Int (4)
 | 
						|
 | 
						|
A 32 bit signed integer.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   4                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   4                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   value (int32)                                               |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   padding                                                     |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## Long (5)
 | 
						|
 | 
						|
A 64 bit signed integer.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   8                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   5                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   value (int64)                                               |
 | 
						|
   +                                                               +
 | 
						|
   |                                                               |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## Float (6)
 | 
						|
 | 
						|
A 32 bit float value.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   4                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   6                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   value (float32)                                             |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   padding                                                     |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## Double (7)
 | 
						|
 | 
						|
A 64 bit float value.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   8                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   7                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   value (float64)                                             |
 | 
						|
   +                                                               +
 | 
						|
   |                                                               |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## String (8)
 | 
						|
 | 
						|
A string. This does not have to be valid UTF8 but it is 0 terminated.
 | 
						|
The size field is set to the length of the string, including the 0
 | 
						|
byte.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   size                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   8                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   chars ....                                                  |
 | 
						|
   .                                                               .
 | 
						|
   |                                            ... 0 | padding..  |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
 | 
						|
## Bytes (9)
 | 
						|
 | 
						|
A byte array.  The size field is set to the number of bytes.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   size                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   9                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   bytes ....                                                  |
 | 
						|
   .                                                               .
 | 
						|
   |                                                  | padding..  |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## Rectangle (10)
 | 
						|
 | 
						|
A Rectangle.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   8                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   10                                                          |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   width (uint32)                                              |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   height (uint32)                                             |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## Fraction (11)
 | 
						|
 | 
						|
A Fraction.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   8                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   11                                                          |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   num (uint32)                                                |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   denom (uint32)                                              |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## Bitmap (12)
 | 
						|
 | 
						|
A bitmap. Stored as bits in uint8. size is the number of bytes with
 | 
						|
bits.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   size                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   12                                                          |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   bits (uint8) ...                                            |
 | 
						|
   .                                                               .
 | 
						|
   |                                                  | padding..  |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## Array (13)
 | 
						|
 | 
						|
An array is an array of (basic) types. In principle the array can contain
 | 
						|
any type as long as each item in the array has the same child_size and
 | 
						|
child_type.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   size                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   13                                                          |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   child_size                                                  |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   child_type                                                  |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   child1 (child_size bytes) ...                               |
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   childN (child_size bytes) ...                               |
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
We describe Array types with a shortcut like:
 | 
						|
 | 
						|
```
 | 
						|
 Array[Int](<val1>,<val2>,...)
 | 
						|
```
 | 
						|
 | 
						|
## Struct (14)
 | 
						|
 | 
						|
Multiple PODs can be combined into a struct:
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   size                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   14  (Struct)                                                |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   size1                                                       |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   type1                                                       |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   payload 1...                                                |
 | 
						|
   .                                                |  ... padding .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   sizeN                                                       |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   typeN                                                       |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   payloadN ...                                                |
 | 
						|
   .                                                |  ... padding .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
We describe Struct types with a shortcut like:
 | 
						|
 | 
						|
```
 | 
						|
 Struct(
 | 
						|
    <pod1 type> : <pod1 description>,
 | 
						|
    <pod2 type> : <pod2 description>,
 | 
						|
    ...)
 | 
						|
```
 | 
						|
 | 
						|
The type of a struct is 14 and the size the total sum in bytes of all
 | 
						|
PODs (with padding) inside the struct.
 | 
						|
 | 
						|
## Object (15)
 | 
						|
 | 
						|
An object contains a set of of properties.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   size                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   15                                                          |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   object_type                                                 |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   object_id                                                   |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   property1                                                   |
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   propertyN                                                   |
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
object_type is one of the well defined object types.
 | 
						|
object_id is extra information about the context of the object.
 | 
						|
 | 
						|
Each property is as follows:
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   key (uint32)                                                |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   flags (uint32)                                              |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   POD value ...                                               |
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
Object are written with a shortcut as:
 | 
						|
 
 | 
						|
```
 | 
						|
 Object[type,id](
 | 
						|
    key1: <pod1>,
 | 
						|
    key2: <pod1>,
 | 
						|
    ...)
 | 
						|
```
 | 
						|
 | 
						|
## Sequence (16)
 | 
						|
 | 
						|
A sequence is a series of times events. It is usually used for transporting
 | 
						|
MIDI and control updates.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   size                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   16                                                          |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   unit                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   pad                                                         |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   control1                                                    |
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   controlN                                                    |
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
The unit field and pad is currently set to 0.
 | 
						|
 | 
						|
Each control look like:
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   offset (uint32)                                             |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   type (uint32)                                               |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   POD value ...                                               |
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
- offset: the offset relative to the current graph clock time.
 | 
						|
- type:   the type of control, see enum spa_control_type
 | 
						|
 | 
						|
 | 
						|
## Pointer (17)
 | 
						|
 | 
						|
A generic pointer to some memory region. Pointer types are usually not serialized.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   16                                                          |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   17                                                          |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   type                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   padding (must be 0)                                         |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   native pointer value ...                                    |
 | 
						|
   .                                               | .. padding    .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
 | 
						|
## Fd (18)
 | 
						|
 | 
						|
A file descriptor stored as int64. When serializing, the file descriptor
 | 
						|
is modified to contain the index of the fd in the message.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   8                                                           |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   18                                                          |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   fd (int64) ...                                              |
 | 
						|
   +                                                               +
 | 
						|
   |                                                               |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
## Choice (19)
 | 
						|
 | 
						|
A choice contains an array of possible values.
 | 
						|
 | 
						|
```
 | 
						|
    0                   1                   2                   3
 | 
						|
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   size                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   19                                                          |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   type                                                        |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   flags                                                       |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   child_size                                                  |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   child_type                                                  |
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   child1 (child_size bytes) ...                               |
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
   |   childN (child_size bytes) ...                               |
 | 
						|
   .                                                               .
 | 
						|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
```
 | 
						|
 | 
						|
- type: one of possible values, see enum spa_choice_type
 | 
						|
    - None (0)   : only child1 is an valid option
 | 
						|
    - Range (1)  : child1 is a default value, options are between
 | 
						|
                   child2 and child3 in the value array.
 | 
						|
    - Step (2)   : child1 is a default value, options are between
 | 
						|
                   child2 and child3, in steps of child4 in the value array.
 | 
						|
    - Enum (3)   : child1 is a default value, options are any value from
 | 
						|
                   the value array, preferred values come first.
 | 
						|
    - Flags (4)  : only child1 is a flag value. When filtering, the flags
 | 
						|
                   are AND-ed together.
 | 
						|
 | 
						|
- flags: must be 0
 | 
						|
 | 
						|
## Pod (20)
 | 
						|
 | 
						|
The value id the POD itself.
 | 
						|
 | 
						|
\addtogroup spa_pod
 | 
						|
 | 
						|
See: \ref page_spa_pod
 | 
						|
 | 
						|
*/
 |