Rework formats

Use a POD for the format body. This allows us to more easily build
and copy the formats.
Remove obsolete code to make video and audio formats.
Use SpaVideo/AudioInfo to keep track of formats. Make functions to parse
the format into the structures.
Update plugins
This commit is contained in:
Wim Taymans 2017-02-24 09:28:18 +01:00
parent 7fc73953cd
commit 16b62de53a
34 changed files with 1096 additions and 1579 deletions

View file

@ -24,216 +24,49 @@
#include <spa/audio/raw.h>
#include <spa/audio/format.h>
#include <lib/props.h>
static const uint32_t format_values[] = {
SPA_AUDIO_FORMAT_S8,
SPA_AUDIO_FORMAT_U8,
/* 16 bit */
SPA_AUDIO_FORMAT_S16LE,
SPA_AUDIO_FORMAT_S16BE,
SPA_AUDIO_FORMAT_U16LE,
SPA_AUDIO_FORMAT_U16BE,
/* 24 bit in low 3 bytes of 32 bits*/
SPA_AUDIO_FORMAT_S24_32LE,
SPA_AUDIO_FORMAT_S24_32BE,
SPA_AUDIO_FORMAT_U24_32LE,
SPA_AUDIO_FORMAT_U24_32BE,
/* 32 bit */
SPA_AUDIO_FORMAT_S32LE,
SPA_AUDIO_FORMAT_S32BE,
SPA_AUDIO_FORMAT_U32LE,
SPA_AUDIO_FORMAT_U32BE,
/* 24 bit in 3 bytes*/
SPA_AUDIO_FORMAT_S24LE,
SPA_AUDIO_FORMAT_S24BE,
SPA_AUDIO_FORMAT_U24LE,
SPA_AUDIO_FORMAT_U24BE,
/* 20 bit in 3 bytes*/
SPA_AUDIO_FORMAT_S20LE,
SPA_AUDIO_FORMAT_S20BE,
SPA_AUDIO_FORMAT_U20LE,
SPA_AUDIO_FORMAT_U20BE,
/* 18 bit in 3 bytes*/
SPA_AUDIO_FORMAT_S18LE,
SPA_AUDIO_FORMAT_S18BE,
SPA_AUDIO_FORMAT_U18LE,
SPA_AUDIO_FORMAT_U18BE,
/* float */
SPA_AUDIO_FORMAT_F32LE,
SPA_AUDIO_FORMAT_F32BE,
SPA_AUDIO_FORMAT_F64LE,
SPA_AUDIO_FORMAT_F64BE
typedef struct {
uint32_t key;
uint32_t type;
off_t offset;
} ParseInfo;
static const ParseInfo raw_parse_info[] = {
{ SPA_PROP_ID_AUDIO_INFO, SPA_POD_TYPE_BYTES, offsetof (SpaAudioInfo, info.raw) },
{ SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.format) },
{ SPA_PROP_ID_AUDIO_FLAGS, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.flags) },
{ SPA_PROP_ID_AUDIO_LAYOUT, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.layout) },
{ SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.rate) },
{ SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.channels) },
{ SPA_PROP_ID_AUDIO_CHANNEL_MASK, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.channel_mask) },
{ 0, }
};
static const SpaPropRangeInfo format_format_range[] = {
{ "S8", { sizeof (uint32_t), &format_values[0] } },
{ "U8", { sizeof (uint32_t), &format_values[1] } },
{ "S16LE", { sizeof (uint32_t), &format_values[2] } },
{ "S16BE", { sizeof (uint32_t), &format_values[3] } },
{ "U16LE", { sizeof (uint32_t), &format_values[4] } },
{ "U16BE", { sizeof (uint32_t), &format_values[5] } },
{ "S24_32LE", { sizeof (uint32_t), &format_values[6] } },
{ "S24_32BE", { sizeof (uint32_t), &format_values[7] } },
{ "U24_32LE", { sizeof (uint32_t), &format_values[8] } },
{ "U24_32BE", { sizeof (uint32_t), &format_values[9] } },
{ "S32LE", { sizeof (uint32_t), &format_values[10] } },
{ "S32BE", { sizeof (uint32_t), &format_values[11] } },
{ "U32LE", { sizeof (uint32_t), &format_values[12] } },
{ "U32BE", { sizeof (uint32_t), &format_values[13] } },
{ "S24LE", { sizeof (uint32_t), &format_values[14] } },
{ "S24BE", { sizeof (uint32_t), &format_values[15] } },
{ "U24LE", { sizeof (uint32_t), &format_values[16] } },
{ "U24BE", { sizeof (uint32_t), &format_values[17] } },
{ "S20LE", { sizeof (uint32_t), &format_values[18] } },
{ "S20BE", { sizeof (uint32_t), &format_values[19] } },
{ "U20LE", { sizeof (uint32_t), &format_values[20] } },
{ "U20BE", { sizeof (uint32_t), &format_values[21] } },
{ "S18LE", { sizeof (uint32_t), &format_values[22] } },
{ "S18BE", { sizeof (uint32_t), &format_values[23] } },
{ "U18LE", { sizeof (uint32_t), &format_values[24] } },
{ "U18BE", { sizeof (uint32_t), &format_values[25] } },
{ "F32LE", { sizeof (uint32_t), &format_values[26] } },
{ "F32BE", { sizeof (uint32_t), &format_values[27] } },
{ "F64LE", { sizeof (uint32_t), &format_values[28] } },
{ "F64BE", { sizeof (uint32_t), &format_values[29] } },
};
static const uint32_t format_layouts[] = {
SPA_AUDIO_LAYOUT_INTERLEAVED,
SPA_AUDIO_LAYOUT_NON_INTERLEAVED,
};
static const SpaPropRangeInfo layouts_range[] = {
{ "interleaved", { sizeof (uint32_t), &format_layouts[0] } },
{ "non-interleaved", { sizeof (uint32_t), &format_layouts[1] } },
};
static const uint32_t format_flags[] = {
SPA_AUDIO_FLAG_NONE,
SPA_AUDIO_FLAG_UNPOSITIONED,
};
static const SpaPropRangeInfo flags_range[] = {
{ "none", { sizeof (uint32_t), &format_flags[0] } },
{ "unpositioned", { sizeof (uint32_t), &format_flags[1] } },
};
static const uint32_t min_uint32 = 1;
static const uint32_t max_uint32 = UINT32_MAX;
static const SpaPropRangeInfo uint32_range[] = {
{ "min", { sizeof (uint32_t), &min_uint32 } },
{ "max", { sizeof (uint32_t), &max_uint32 } },
};
static const SpaPropInfo format_prop_info[] =
static const ParseInfo *
parse_info_find (const ParseInfo *info, uint32_t key, uint32_t type)
{
{ SPA_PROP_ID_AUDIO_INFO, 0,
"info",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL | SPA_PROP_FLAG_INFO,
SPA_PROP_TYPE_POINTER, sizeof (SpaAudioInfoRaw),
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
NULL },
{ SPA_PROP_ID_AUDIO_FORMAT, 0,
"format",
SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_format_range), format_format_range,
NULL },
{ SPA_PROP_ID_AUDIO_FLAGS, 0,
"flags",
SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (flags_range), flags_range,
NULL },
{ SPA_PROP_ID_AUDIO_LAYOUT, 0,
"layout",
SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (layouts_range), layouts_range,
NULL },
{ SPA_PROP_ID_AUDIO_RATE, 0,
"rate",
SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
NULL },
{ SPA_PROP_ID_AUDIO_CHANNELS, 0,
"channels",
SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
NULL },
{ SPA_PROP_ID_AUDIO_CHANNEL_MASK, 0,
"channel-mask",
SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_BITMASK, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
NULL },
};
SpaResult
spa_prop_info_fill_audio (SpaPropInfo *info,
SpaPropIdAudio id,
size_t offset)
{
int i;
if (info == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
i = id - SPA_PROP_ID_MEDIA_CUSTOM_START;
if (i < 0 || i >= SPA_N_ELEMENTS (format_prop_info))
return SPA_RESULT_INVALID_PROPERTY_INDEX;
memcpy (info, &format_prop_info[i], sizeof (SpaPropInfo));
info->offset = offset - sizeof (SpaFormat) + sizeof (SpaProps);
return SPA_RESULT_OK;
while (info->key) {
if (info->key == key && info->type == type)
return info;
info++;
}
return NULL;
}
SpaResult
spa_format_audio_init (SpaMediaType type,
SpaMediaSubType subtype,
SpaFormatAudio *format)
spa_format_audio_parse (const SpaFormat *format,
SpaAudioInfo *info)
{
SpaPropInfo *prop_info = NULL;
unsigned int n_prop_info = 0;
int i;
SpaPODProp *prop;
const ParseInfo *pinfo, *find;
if (type != SPA_MEDIA_TYPE_AUDIO)
return SPA_RESULT_INVALID_ARGUMENTS;
if (format->media_type != SPA_MEDIA_TYPE_AUDIO)
return SPA_RESULT_INVALID_MEDIA_TYPE;
switch (subtype) {
switch (format->media_subtype) {
case SPA_MEDIA_SUBTYPE_RAW:
{
static SpaPropInfo raw_format_prop_info[] =
{
{ SPA_PROP_ID_AUDIO_INFO, offsetof (SpaFormatAudio, info), },
{ SPA_PROP_ID_AUDIO_FORMAT, offsetof (SpaFormatAudio, info.raw.format), },
{ SPA_PROP_ID_AUDIO_FLAGS, offsetof (SpaFormatAudio, info.raw.flags), },
{ SPA_PROP_ID_AUDIO_LAYOUT, offsetof (SpaFormatAudio, info.raw.layout), },
{ SPA_PROP_ID_AUDIO_RATE, offsetof (SpaFormatAudio, info.raw.rate), },
{ SPA_PROP_ID_AUDIO_CHANNELS, offsetof (SpaFormatAudio, info.raw.channels), },
{ SPA_PROP_ID_AUDIO_CHANNEL_MASK, offsetof (SpaFormatAudio, info.raw.channel_mask), },
};
static const SpaAudioInfoRaw default_raw_info = {
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FLAG_NONE,
SPA_AUDIO_LAYOUT_INTERLEAVED,
44100,
2,
0
};
prop_info = raw_format_prop_info;
n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info);
format->format.props.unset_mask = (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5);
format->info.raw = default_raw_info;
pinfo = raw_parse_info;
break;
}
case SPA_MEDIA_SUBTYPE_MP3:
case SPA_MEDIA_SUBTYPE_AAC:
case SPA_MEDIA_SUBTYPE_VORBIS:
@ -246,78 +79,21 @@ spa_format_audio_init (SpaMediaType type,
case SPA_MEDIA_SUBTYPE_G729:
case SPA_MEDIA_SUBTYPE_AMR:
case SPA_MEDIA_SUBTYPE_GSM:
break;
return SPA_RESULT_NOT_IMPLEMENTED;
default:
return SPA_RESULT_INVALID_ARGUMENTS;
}
if (prop_info && prop_info[0].name == NULL) {
for (i = 0; i < n_prop_info; i++)
spa_prop_info_fill_audio (&prop_info[i],
prop_info[i].id,
prop_info[i].offset);
info->media_type = format->media_type;
info->media_subtype = format->media_subtype;
SPA_POD_OBJECT_BODY_FOREACH (&format->obj.body, format->obj.pod.size, prop) {
if ((find = parse_info_find (pinfo, prop->body.key, prop->body.value.type))) {
memcpy (SPA_MEMBER (info, find->offset, void),
SPA_POD_BODY (&prop->body.value),
SPA_POD_BODY_SIZE (&prop->body.value));
}
}
format->format.media_type = type;
format->format.media_subtype = subtype;
format->format.props.n_prop_info = n_prop_info;
format->format.props.prop_info = prop_info;
return SPA_RESULT_OK;
}
SpaResult
spa_format_audio_parse (const SpaFormat *format,
SpaFormatAudio *aformat)
{
SpaPropValue value;
const SpaProps *props;
SpaResult res;
unsigned int idx;
if ((void *)format == (void *)aformat)
return SPA_RESULT_OK;
if (format->media_type != SPA_MEDIA_TYPE_AUDIO)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if ((res = spa_format_audio_init (format->media_type,
format->media_subtype,
aformat)) < 0)
return res;
props = &format->props;
idx = spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_INFO);
if ((res = spa_props_get_value (props, idx, &value)) < 0)
goto fallback;
if (props->prop_info[idx].type != SPA_PROP_TYPE_POINTER)
goto fallback;
memcpy (&aformat->info, value.value, SPA_MIN (value.size, sizeof (aformat->info)));
aformat->format.props.unset_mask = props->unset_mask;
return SPA_RESULT_OK;
fallback:
res = spa_props_copy_values (props, &aformat->format.props);
return res;
}
SpaResult
spa_format_audio_filter (SpaFormatAudio *format,
const SpaFormat *filter)
{
SpaFormatAudio af;
SpaResult res;
if (filter == NULL)
return SPA_RESULT_OK;
if ((res = spa_format_audio_parse (filter, &af)) != SPA_RESULT_OK)
return res;
return SPA_RESULT_NOT_IMPLEMENTED;
}

View file

@ -20,9 +20,8 @@
#include <stdio.h>
#include "debug.h"
#include "props.h"
struct meta_type_name {
static const struct meta_type_name {
const char *name;
} meta_type_names[] = {
{ "invalid" },
@ -35,7 +34,7 @@ struct meta_type_name {
};
#define META_TYPE_NAME(t) meta_type_names[SPA_CLAMP(t,0,SPA_N_ELEMENTS(meta_type_names)-1)].name
struct data_type_name {
static const struct data_type_name {
const char *name;
} data_type_names[] = {
{ "invalid" },
@ -225,19 +224,58 @@ spa_debug_dump_mem (const void *mem, size_t size)
return SPA_RESULT_OK;
}
struct media_type_name {
SpaResult
spa_debug_props (const SpaProps *props, bool print_ranges)
{
return SPA_RESULT_OK;
}
static const char* media_audio_prop_names[] = {
"info",
"format",
"flags",
"layout",
"rate",
"channels",
"channel-mask",
};
static const char* media_video_prop_names[] = {
"info",
"format",
"size",
"framerate",
"max-framerate",
"views",
"interlace-mode",
"pixel-aspect-ratio",
"multiview-mode",
"multiview-flags",
"chroma-site",
"color-range",
"color-matrix",
"transfer-function",
"color-primaries",
"profile",
"stream-format",
"alignment",
};
static const struct media_type_name {
const char *name;
unsigned int first;
unsigned int last;
unsigned int idx;
const char **prop_names;
} media_type_names[] = {
{ "invalid", 0, 0, 0 },
{ "audio", SPA_MEDIA_SUBTYPE_AUDIO_FIRST, SPA_MEDIA_SUBTYPE_AUDIO_LAST, 16 },
{ "video", SPA_MEDIA_SUBTYPE_VIDEO_FIRST, SPA_MEDIA_SUBTYPE_VIDEO_LAST, 2 },
{ "audio", SPA_MEDIA_SUBTYPE_AUDIO_FIRST, SPA_MEDIA_SUBTYPE_AUDIO_LAST, 16, media_audio_prop_names },
{ "video", SPA_MEDIA_SUBTYPE_VIDEO_FIRST, SPA_MEDIA_SUBTYPE_VIDEO_LAST, 2, media_video_prop_names },
{ "image", 0, 0 },
};
struct media_subtype_name {
static const struct media_subtype_name {
const char *name;
} media_subtype_names[] = {
{ "invalid" },
@ -273,222 +311,184 @@ struct media_subtype_name {
{ "gsm" },
};
struct prop_type_name {
struct pod_type_name {
const char *name;
const char *CCName;
} prop_type_names[] = {
} pod_type_names[] = {
{ "invalid", "*Invalid*" },
{ "bool", "Boolean" },
{ "int8", "Int8" },
{ "uint8", "UInt8" },
{ "int16", "Int16" },
{ "uint16", "UInt16" },
{ "int32", "Int32" },
{ "uint32", "UInt32" },
{ "int64", "Int64" },
{ "uint64", "UInt64" },
{ "bool", "Bool" },
{ "int", "Int" },
{ "uint", "UInt" },
{ "long", "Long" },
{ "float", "Float" },
{ "double", "Double" },
{ "string", "String" },
{ "rectangle", "Rectangle" },
{ "fraction", "Fraction" },
{ "bitmask", "Bitmask" },
{ "pointer", "Pointer" },
{ "array", "Array" },
{ "struct", "Struct" },
{ "object", "Object" },
{ "prop", "Prop" },
{ "bytes", "Bytes" },
};
static void
print_value (const SpaPropInfo *info, const SpaPropValue *val)
print_pod_value (uint32_t size, uint32_t type, void *body, int prefix)
{
SpaPropType type = info->type;
bool enum_string = false;
const void *enum_value;
switch (type) {
case SPA_POD_TYPE_BOOL:
printf ("%-*sBool %d\n", prefix, "", *(int32_t *) body);
break;
case SPA_POD_TYPE_INT:
printf ("%-*sInt %d\n", prefix, "", *(int32_t *) body);
break;
case SPA_POD_TYPE_LONG:
printf ("%-*sLong %"PRIi64"\n", prefix, "", *(int64_t *) body);
break;
case SPA_POD_TYPE_FLOAT:
printf ("%-*sFloat %f\n", prefix, "", *(float *) body);
break;
case SPA_POD_TYPE_DOUBLE:
printf ("%-*sDouble %g\n", prefix, "", *(double *) body);
break;
case SPA_POD_TYPE_STRING:
printf ("%-*sString %s\n", prefix, "", (char *) body);
break;
case SPA_POD_TYPE_RECTANGLE:
{
SpaRectangle *r = body;
printf ("%-*sRectangle %dx%d\n", prefix, "", r->width, r->height);
break;
}
case SPA_POD_TYPE_FRACTION:
{
SpaFraction *f = body;
printf ("%-*sFraction %d/%d\n", prefix, "", f->num, f->denom);
break;
}
case SPA_POD_TYPE_BITMASK:
printf ("%-*sBitmask\n", prefix, "");
break;
case SPA_POD_TYPE_ARRAY:
{
SpaPODArrayBody *b = body;
void *p;
printf ("%-*sArray: child.size %d, child.type %d\n", prefix, "", b->child.size, b->child.type);
if (info->range_type == SPA_PROP_RANGE_TYPE_ENUM) {
int i;
SPA_POD_ARRAY_BODY_FOREACH (b, size, p)
print_pod_value (b->child.size, b->child.type, p, prefix + 2);
break;
}
case SPA_POD_TYPE_STRUCT:
{
SpaPOD *b = body, *p;
printf ("%-*sStruct: size %d\n", prefix, "", size);
SPA_POD_STRUCT_BODY_FOREACH (b, size, p)
print_pod_value (p->size, p->type, SPA_POD_BODY (p), prefix + 2);
break;
}
case SPA_POD_TYPE_OBJECT:
{
SpaPODObjectBody *b = body;
SpaPODProp *p;
void *alt;
int i;
for (i = 0; i < info->n_range_values; i++) {
if (memcmp (info->range_values[i].val.value, val->value, val->size) == 0) {
if (info->range_values[i].name) {
enum_value = info->range_values[i].name;
enum_string = true;
printf ("%-*sObject: size %d\n", prefix, "", size);
SPA_POD_OBJECT_BODY_FOREACH (b, size, p) {
printf ("%-*sProp: key %d, flags %d\n", prefix + 2, "", p->body.key, p->body.flags);
if (p->body.flags & SPA_POD_PROP_FLAG_UNSET)
printf ("%-*sUnset (Default):\n", prefix + 4, "");
else
printf ("%-*sValue:\n", prefix + 4, "");
print_pod_value (p->body.value.size, p->body.value.type, SPA_POD_BODY (&p->body.value), prefix + 6);
i = 0;
SPA_POD_PROP_ALTERNATIVE_FOREACH (&p->body, p->pod.size, alt) {
if (i == 0)
printf ("%-*sAlternatives:\n", prefix + 4, "");
print_pod_value (p->body.value.size, p->body.value.type, alt, prefix + 6);
i++;
}
}
break;
}
}
}
SpaResult
spa_debug_pod (const SpaPOD *pod)
{
print_pod_value (pod->size, pod->type, SPA_POD_BODY (pod), 0);
return SPA_RESULT_OK;
}
static void
print_format_value (uint32_t size, uint32_t type, void *body)
{
switch (type) {
case SPA_PROP_TYPE_INVALID:
fprintf (stderr, "invalid");
case SPA_POD_TYPE_BOOL:
fprintf (stderr, "%s", *(int32_t *) body ? "true" : "false");
break;
case SPA_PROP_TYPE_BOOL:
fprintf (stderr, "%s", *(bool *)val->value ? "true" : "false");
case SPA_POD_TYPE_INT:
fprintf (stderr, "%"PRIi32, *(int32_t *) body);
break;
case SPA_PROP_TYPE_INT8:
fprintf (stderr, "%" PRIi8, *(int8_t *)val->value);
case SPA_POD_TYPE_LONG:
fprintf (stderr, "%"PRIi64, *(int64_t *) body);
break;
case SPA_PROP_TYPE_UINT8:
fprintf (stderr, "%" PRIu8, *(uint8_t *)val->value);
case SPA_POD_TYPE_FLOAT:
fprintf (stderr, "%f", *(float *) body);
break;
case SPA_PROP_TYPE_INT16:
fprintf (stderr, "%" PRIi16, *(int16_t *)val->value);
case SPA_POD_TYPE_DOUBLE:
fprintf (stderr, "%g", *(double *) body);
break;
case SPA_PROP_TYPE_UINT16:
fprintf (stderr, "%" PRIu16, *(uint16_t *)val->value);
case SPA_POD_TYPE_STRING:
fprintf (stderr, "%s", (char *) body);
break;
case SPA_PROP_TYPE_INT32:
fprintf (stderr, "%" PRIi32, *(int32_t *)val->value);
break;
case SPA_PROP_TYPE_UINT32:
fprintf (stderr, "%" PRIu32, *(uint32_t *)val->value);
break;
case SPA_PROP_TYPE_INT64:
fprintf (stderr, "%" PRIi64 "\n", *(int64_t *)val->value);
break;
case SPA_PROP_TYPE_UINT64:
fprintf (stderr, "%" PRIu64 "\n", *(uint64_t *)val->value);
break;
case SPA_PROP_TYPE_INT:
fprintf (stderr, "%d", *(int *)val->value);
break;
case SPA_PROP_TYPE_UINT:
fprintf (stderr, "%u", *(unsigned int *)val->value);
break;
case SPA_PROP_TYPE_FLOAT:
fprintf (stderr, "%f", *(float *)val->value);
break;
case SPA_PROP_TYPE_DOUBLE:
fprintf (stderr, "%g", *(double *)val->value);
break;
case SPA_PROP_TYPE_STRING:
fprintf (stderr, "\"%s\"", (char *)val->value);
break;
case SPA_PROP_TYPE_RECTANGLE:
case SPA_POD_TYPE_RECTANGLE:
{
const SpaRectangle *r = val->value;
SpaRectangle *r = body;
fprintf (stderr, "%"PRIu32"x%"PRIu32, r->width, r->height);
break;
}
case SPA_PROP_TYPE_FRACTION:
case SPA_POD_TYPE_FRACTION:
{
const SpaFraction *f = val->value;
SpaFraction *f = body;
fprintf (stderr, "%"PRIu32"/%"PRIu32, f->num, f->denom);
break;
}
case SPA_PROP_TYPE_BITMASK:
break;
case SPA_PROP_TYPE_POINTER:
fprintf (stderr, "%p", val->value);
case SPA_POD_TYPE_BITMASK:
fprintf (stderr, "Bitmask");
break;
default:
break;
}
if (enum_string)
fprintf (stderr, " (%s)", (char *)enum_value);
}
SpaResult
spa_debug_props (const SpaProps *props, bool print_ranges)
{
SpaResult res;
const SpaPropInfo *info;
int i, j;
if (props == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
fprintf (stderr, "Properties (%d items):\n", props->n_prop_info);
for (i = 0; i < props->n_prop_info; i++) {
SpaPropValue value;
info = &props->prop_info[i];
fprintf (stderr, " %-20s flags: ", info->name);
if (info->flags & SPA_PROP_FLAG_READABLE)
fprintf (stderr, "readable ");
if (info->flags & SPA_PROP_FLAG_WRITABLE)
fprintf (stderr, "writable ");
if (info->flags & SPA_PROP_FLAG_OPTIONAL)
fprintf (stderr, "optional ");
if (info->flags & SPA_PROP_FLAG_DEPRECATED)
fprintf (stderr, "deprecated ");
fprintf (stderr, "\n");
fprintf (stderr, "%-23.23s %s. ", "", prop_type_names[info->type].CCName);
res = spa_props_get_value (props, i, &value);
fprintf (stderr, "Current: ");
if (res == SPA_RESULT_OK)
print_value (info, &value);
else if (res == SPA_RESULT_PROPERTY_UNSET)
fprintf (stderr, "Unset");
else
fprintf (stderr, "Error %d", res);
fprintf (stderr, ".\n");
if (!print_ranges)
continue;
if (info->range_type != SPA_PROP_RANGE_TYPE_NONE) {
fprintf (stderr, "%-23.23s ", "");
switch (info->range_type) {
case SPA_PROP_RANGE_TYPE_MIN_MAX:
fprintf (stderr, "Range");
break;
case SPA_PROP_RANGE_TYPE_STEP:
fprintf (stderr, "Step");
break;
case SPA_PROP_RANGE_TYPE_ENUM:
fprintf (stderr, "Enum");
break;
case SPA_PROP_RANGE_TYPE_FLAGS:
fprintf (stderr, "Flags");
break;
default:
fprintf (stderr, "Unknown");
break;
}
fprintf (stderr, ".\n");
for (j = 0; j < info->n_range_values; j++) {
const SpaPropRangeInfo *rinfo = &info->range_values[j];
fprintf (stderr, "%-23.23s ", "");
print_value (info, &rinfo->val);
fprintf (stderr, "\t: %-12s\n", rinfo->name);
}
}
if (info->extra) {
fprintf (stderr, "Extra info: \n");
spa_debug_dict (info->extra);
}
}
return SPA_RESULT_OK;
}
SpaResult
spa_debug_format (const SpaFormat *format)
{
const SpaProps *props;
int i, first, last, idx;
const char *media_type;
const char *media_subtype;
const char **prop_names;
SpaPODProp *prop;
if (format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
props = &format->props;
if (format->media_type > 0 && format->media_type < SPA_N_ELEMENTS (media_type_names)) {
media_type = media_type_names[format->media_type].name;
first = media_type_names[format->media_type].first;
last = media_type_names[format->media_type].last;
idx = media_type_names[format->media_type].idx;
prop_names = media_type_names[format->media_type].prop_names;
}
else {
media_type = "unknown";
idx = first = last = -1;
prop_names = NULL;
}
if (format->media_subtype >= SPA_MEDIA_SUBTYPE_ANY_FIRST &&
@ -501,35 +501,28 @@ spa_debug_format (const SpaFormat *format)
fprintf (stderr, "%-6s %s/%s\n", "", media_type, media_subtype);
for (i = 0; i < props->n_prop_info; i++) {
const SpaPropInfo *info = &props->prop_info[i];
SpaPropValue value;
SpaResult res;
res = spa_props_get_value (props, i, &value);
if (info->flags & SPA_PROP_FLAG_INFO)
continue;
if (res == SPA_RESULT_PROPERTY_UNSET && info->flags & SPA_PROP_FLAG_OPTIONAL)
SPA_POD_OBJECT_BODY_FOREACH (&format->obj.body, format->obj.pod.size, prop) {
if ((prop->body.flags & SPA_POD_PROP_FLAG_UNSET) &&
(prop->body.flags & SPA_POD_PROP_FLAG_OPTIONAL))
continue;
fprintf (stderr, " %20s : (%s) ", info->name, prop_type_names[info->type].name);
if (res == SPA_RESULT_OK) {
print_value (info, &value);
} else if (res == SPA_RESULT_PROPERTY_UNSET) {
int j;
fprintf (stderr, " %20s : (%s) ", prop_names[prop->body.key - SPA_PROP_ID_MEDIA_CUSTOM_START], pod_type_names[prop->body.value.type].name);
if (!(prop->body.flags & SPA_POD_PROP_FLAG_UNSET)) {
print_format_value (prop->body.value.size, prop->body.value.type, SPA_POD_BODY (&prop->body.value));
} else {
const char *ssep, *esep, *sep;
void *alt;
switch (info->range_type) {
case SPA_PROP_RANGE_TYPE_MIN_MAX:
case SPA_PROP_RANGE_TYPE_STEP:
switch (prop->body.flags & SPA_POD_PROP_RANGE_MASK) {
case SPA_POD_PROP_RANGE_MIN_MAX:
case SPA_POD_PROP_RANGE_STEP:
ssep = "[ ";
sep = ", ";
esep = " ]";
break;
default:
case SPA_PROP_RANGE_TYPE_ENUM:
case SPA_PROP_RANGE_TYPE_FLAGS:
case SPA_POD_PROP_RANGE_ENUM:
case SPA_POD_PROP_RANGE_FLAGS:
ssep = "{ ";
sep = ", ";
esep = " }";
@ -537,14 +530,15 @@ spa_debug_format (const SpaFormat *format)
}
fprintf (stderr, ssep);
for (j = 0; j < info->n_range_values; j++) {
const SpaPropRangeInfo *rinfo = &info->range_values[j];
print_value (info, &rinfo->val);
fprintf (stderr, "%s", j + 1 < info->n_range_values ? sep : "");
i = 0;
SPA_POD_PROP_ALTERNATIVE_FOREACH (&prop->body, prop->pod.size, alt) {
if (i > 0)
fprintf (stderr, "%s", sep);
print_format_value (prop->body.value.size, prop->body.value.type, alt);
i++;
}
fprintf (stderr, esep);
} else {
fprintf (stderr, "*Error*");
}
fprintf (stderr, "\n");
}

View file

@ -27,12 +27,14 @@ extern "C" {
#include <spa/defs.h>
#include <spa/port.h>
#include <spa/buffer.h>
#include <spa/pod.h>
#include <spa/props.h>
#include <spa/format.h>
#include <spa/dict.h>
SpaResult spa_debug_port_info (const SpaPortInfo *info);
SpaResult spa_debug_buffer (const SpaBuffer *buffer);
SpaResult spa_debug_pod (const SpaPOD *pod);
SpaResult spa_debug_props (const SpaProps *props, bool print_ranges);
SpaResult spa_debug_format (const SpaFormat *format);
SpaResult spa_debug_dump_mem (const void *data, size_t size);

View file

@ -24,551 +24,80 @@
#include <spa/video/raw.h>
#include <spa/video/format.h>
#include <spa/format-builder.h>
#include "video-raw.h"
#include "props.h"
typedef struct {
uint32_t key;
uint32_t type;
off_t offset;
} ParseInfo;
static const uint32_t format_values[] = {
SPA_VIDEO_FORMAT_UNKNOWN,
SPA_VIDEO_FORMAT_ENCODED,
SPA_VIDEO_FORMAT_I420,
SPA_VIDEO_FORMAT_YV12,
SPA_VIDEO_FORMAT_YUY2,
SPA_VIDEO_FORMAT_UYVY,
SPA_VIDEO_FORMAT_AYUV,
SPA_VIDEO_FORMAT_RGBx,
SPA_VIDEO_FORMAT_BGRx,
SPA_VIDEO_FORMAT_xRGB,
SPA_VIDEO_FORMAT_xBGR,
SPA_VIDEO_FORMAT_RGBA,
SPA_VIDEO_FORMAT_BGRA,
SPA_VIDEO_FORMAT_ARGB,
SPA_VIDEO_FORMAT_ABGR,
SPA_VIDEO_FORMAT_RGB,
SPA_VIDEO_FORMAT_BGR,
SPA_VIDEO_FORMAT_Y41B,
SPA_VIDEO_FORMAT_Y42B,
SPA_VIDEO_FORMAT_YVYU,
SPA_VIDEO_FORMAT_Y444,
SPA_VIDEO_FORMAT_v210,
SPA_VIDEO_FORMAT_v216,
SPA_VIDEO_FORMAT_NV12,
SPA_VIDEO_FORMAT_NV21,
SPA_VIDEO_FORMAT_GRAY8,
SPA_VIDEO_FORMAT_GRAY16_BE,
SPA_VIDEO_FORMAT_GRAY16_LE,
SPA_VIDEO_FORMAT_v308,
SPA_VIDEO_FORMAT_RGB16,
SPA_VIDEO_FORMAT_BGR16,
SPA_VIDEO_FORMAT_RGB15,
SPA_VIDEO_FORMAT_BGR15,
SPA_VIDEO_FORMAT_UYVP,
SPA_VIDEO_FORMAT_A420,
SPA_VIDEO_FORMAT_RGB8P,
SPA_VIDEO_FORMAT_YUV9,
SPA_VIDEO_FORMAT_YVU9,
SPA_VIDEO_FORMAT_IYU1,
SPA_VIDEO_FORMAT_ARGB64,
SPA_VIDEO_FORMAT_AYUV64,
SPA_VIDEO_FORMAT_r210,
SPA_VIDEO_FORMAT_I420_10BE,
SPA_VIDEO_FORMAT_I420_10LE,
SPA_VIDEO_FORMAT_I422_10BE,
SPA_VIDEO_FORMAT_I422_10LE,
SPA_VIDEO_FORMAT_Y444_10BE,
SPA_VIDEO_FORMAT_Y444_10LE,
SPA_VIDEO_FORMAT_GBR,
SPA_VIDEO_FORMAT_GBR_10BE,
SPA_VIDEO_FORMAT_GBR_10LE,
SPA_VIDEO_FORMAT_NV16,
SPA_VIDEO_FORMAT_NV24,
SPA_VIDEO_FORMAT_NV12_64Z32,
SPA_VIDEO_FORMAT_A420_10BE,
SPA_VIDEO_FORMAT_A420_10LE,
SPA_VIDEO_FORMAT_A422_10BE,
SPA_VIDEO_FORMAT_A422_10LE,
SPA_VIDEO_FORMAT_A444_10BE,
SPA_VIDEO_FORMAT_A444_10LE,
SPA_VIDEO_FORMAT_NV61,
SPA_VIDEO_FORMAT_P010_10BE,
SPA_VIDEO_FORMAT_P010_10LE,
SPA_VIDEO_FORMAT_IYU2,
static const ParseInfo raw_parse_info[] = {
{ SPA_PROP_ID_VIDEO_INFO, SPA_POD_TYPE_BYTES, offsetof (SpaVideoInfo, info.raw) },
{ SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.format) },
{ SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE, offsetof (SpaVideoInfo, info.raw.size) },
{ SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.raw.framerate) },
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.raw.max_framerate) },
{ SPA_PROP_ID_VIDEO_VIEWS, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.views) },
{ SPA_PROP_ID_VIDEO_INTERLACE_MODE, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.interlace_mode) },
{ SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.raw.pixel_aspect_ratio) },
{ SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.multiview_mode) },
{ SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.multiview_flags) },
{ SPA_PROP_ID_VIDEO_CHROMA_SITE, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.chroma_site) },
{ SPA_PROP_ID_VIDEO_COLOR_RANGE, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.color_range) },
{ SPA_PROP_ID_VIDEO_COLOR_MATRIX, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.color_matrix) },
{ SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.transfer_function) },
{ SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.color_primaries) },
{ 0, }
};
static const SpaPropRangeInfo format_range[] = {
{ "UNKNOWN", { sizeof (uint32_t), &format_values[0] } },
{ "ENCODED", { sizeof (uint32_t), &format_values[1] } },
{ "I420", { sizeof (uint32_t), &format_values[2] } },
{ "YV12", { sizeof (uint32_t), &format_values[3] } },
{ "YUY2", { sizeof (uint32_t), &format_values[4] } },
{ "UYVY", { sizeof (uint32_t), &format_values[5] } },
{ "AYUV", { sizeof (uint32_t), &format_values[6] } },
{ "RGBx", { sizeof (uint32_t), &format_values[7] } },
{ "BGRx", { sizeof (uint32_t), &format_values[8] } },
{ "xRGB", { sizeof (uint32_t), &format_values[9] } },
{ "xBGR", { sizeof (uint32_t), &format_values[10] } },
{ "RGBA", { sizeof (uint32_t), &format_values[11] } },
{ "BGRA", { sizeof (uint32_t), &format_values[12] } },
{ "ARGB", { sizeof (uint32_t), &format_values[13] } },
{ "ABGR", { sizeof (uint32_t), &format_values[14] } },
{ "RGB", { sizeof (uint32_t), &format_values[15] } },
{ "BGR", { sizeof (uint32_t), &format_values[16] } },
{ "Y41B", { sizeof (uint32_t), &format_values[17] } },
{ "Y42B", { sizeof (uint32_t), &format_values[18] } },
{ "YVYU", { sizeof (uint32_t), &format_values[19] } },
{ "Y444", { sizeof (uint32_t), &format_values[20] } },
{ "v210", { sizeof (uint32_t), &format_values[21] } },
{ "v216", { sizeof (uint32_t), &format_values[22] } },
{ "NV12", { sizeof (uint32_t), &format_values[23] } },
{ "NV21", { sizeof (uint32_t), &format_values[24] } },
{ "GRAY8", { sizeof (uint32_t), &format_values[25] } },
{ "GRAY16_BE", { sizeof (uint32_t), &format_values[26] } },
{ "GRAY16_LE", { sizeof (uint32_t), &format_values[27] } },
{ "v308", { sizeof (uint32_t), &format_values[28] } },
{ "RGB16", { sizeof (uint32_t), &format_values[29] } },
{ "BGR16", { sizeof (uint32_t), &format_values[30] } },
{ "RGB15", { sizeof (uint32_t), &format_values[31] } },
{ "BGR15", { sizeof (uint32_t), &format_values[32] } },
{ "UYVP", { sizeof (uint32_t), &format_values[33] } },
{ "A420", { sizeof (uint32_t), &format_values[34] } },
{ "RGB8P", { sizeof (uint32_t), &format_values[35] } },
{ "YUV9", { sizeof (uint32_t), &format_values[36] } },
{ "YVU9", { sizeof (uint32_t), &format_values[37] } },
{ "IYU1", { sizeof (uint32_t), &format_values[38] } },
{ "ARGB64", { sizeof (uint32_t), &format_values[39] } },
{ "AYUV64", { sizeof (uint32_t), &format_values[40] } },
{ "r210", { sizeof (uint32_t), &format_values[41] } },
{ "I420_10BE", { sizeof (uint32_t), &format_values[42] } },
{ "I420_10LE", { sizeof (uint32_t), &format_values[43] } },
{ "I422_10BE", { sizeof (uint32_t), &format_values[44] } },
{ "I422_10LE", { sizeof (uint32_t), &format_values[45] } },
{ "I444_10BE", { sizeof (uint32_t), &format_values[46] } },
{ "I444_10LE", { sizeof (uint32_t), &format_values[47] } },
{ "GBR", { sizeof (uint32_t), &format_values[48] } },
{ "GBR_10BE", { sizeof (uint32_t), &format_values[49] } },
{ "GBR_10LE", { sizeof (uint32_t), &format_values[50] } },
{ "NV16", { sizeof (uint32_t), &format_values[51] } },
{ "NV24", { sizeof (uint32_t), &format_values[52] } },
{ "NV12_64Z32", { sizeof (uint32_t), &format_values[53] } },
{ "A420_10BE", { sizeof (uint32_t), &format_values[54] } },
{ "A420_10LE", { sizeof (uint32_t), &format_values[55] } },
{ "A422_10BE", { sizeof (uint32_t), &format_values[56] } },
{ "A422_10LE", { sizeof (uint32_t), &format_values[57] } },
{ "A444_10BE", { sizeof (uint32_t), &format_values[58] } },
{ "A444_10LE", { sizeof (uint32_t), &format_values[59] } },
{ "NV61", { sizeof (uint32_t), &format_values[60] } },
{ "P010_10BE", { sizeof (uint32_t), &format_values[61] } },
{ "P010_10LE", { sizeof (uint32_t), &format_values[62] } },
{ "IYU2", { sizeof (uint32_t), &format_values[63] } },
static const ParseInfo h264_parse_info[] = {
{ SPA_PROP_ID_VIDEO_INFO, SPA_POD_TYPE_BYTES, offsetof (SpaVideoInfo, info.h264) },
{ SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE, offsetof (SpaVideoInfo, info.h264.size) },
{ SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.h264.framerate) },
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.h264.max_framerate) },
{ 0, }
};
static const SpaRectangle min_size = { 1, 1 };
static const SpaRectangle max_size = { UINT32_MAX, UINT32_MAX };
static const SpaPropRangeInfo size_range[] = {
{ "min", { sizeof (SpaRectangle), &min_size } },
{ "max", { sizeof (SpaRectangle), &max_size } },
static const ParseInfo mjpg_parse_info[] = {
{ SPA_PROP_ID_VIDEO_INFO, SPA_POD_TYPE_BYTES, offsetof (SpaVideoInfo, info.h264) },
{ SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE, offsetof (SpaVideoInfo, info.h264.size) },
{ SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.h264.framerate) },
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.h264.max_framerate) },
{ 0, }
};
static const uint32_t interlace_modes[] = {
SPA_VIDEO_INTERLACE_MODE_PROGRESSIVE,
SPA_VIDEO_INTERLACE_MODE_INTERLEAVED,
SPA_VIDEO_INTERLACE_MODE_MIXED,
SPA_VIDEO_INTERLACE_MODE_FIELDS
};
static const SpaPropRangeInfo interlace_mode_range[] = {
{ "progressive", { sizeof (uint32_t), &interlace_modes[0] } },
{ "interleaved", { sizeof (uint32_t), &interlace_modes[1] } },
{ "mixed", { sizeof (uint32_t), &interlace_modes[2] } },
{ "fields", { sizeof (uint32_t), &interlace_modes[3] } },
};
static const uint32_t multiview_modes[] = {
SPA_VIDEO_MULTIVIEW_MODE_NONE,
SPA_VIDEO_MULTIVIEW_MODE_MONO,
SPA_VIDEO_MULTIVIEW_MODE_LEFT,
SPA_VIDEO_MULTIVIEW_MODE_RIGHT,
SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE,
SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX,
SPA_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED,
SPA_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED,
SPA_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM,
SPA_VIDEO_MULTIVIEW_MODE_CHECKERBOARD,
SPA_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME,
SPA_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME,
SPA_VIDEO_MULTIVIEW_MODE_SEPARATED
};
static const SpaPropRangeInfo multiview_mode_range[] = {
{ "unknown", { sizeof (uint32_t), &multiview_modes[0] } },
{ "mono", { sizeof (uint32_t), &multiview_modes[1] } },
{ "left", { sizeof (uint32_t), &multiview_modes[2] } },
{ "right", { sizeof (uint32_t), &multiview_modes[3] } },
{ "side-by-side", { sizeof (uint32_t), &multiview_modes[4] } },
{ "side-by-side-quincunx", { sizeof (uint32_t), &multiview_modes[5] } },
{ "column-interleaved", { sizeof (uint32_t), &multiview_modes[6] } },
{ "row-interleaved", { sizeof (uint32_t), &multiview_modes[7] } },
{ "top-bottom", { sizeof (uint32_t), &multiview_modes[8] } },
{ "checkerboard", { sizeof (uint32_t), &multiview_modes[9] } },
{ "frame-by-frame", { sizeof (uint32_t), &multiview_modes[10] } },
{ "multiview-frame-by-frame", { sizeof (uint32_t), &multiview_modes[11] } },
{ "separated", { sizeof (uint32_t), &multiview_modes[12] } },
};
static const uint32_t multiview_flags[] = {
SPA_VIDEO_MULTIVIEW_FLAGS_NONE,
SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST,
SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED,
SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED,
SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED,
SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED,
SPA_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT,
SPA_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO,
};
static const SpaPropRangeInfo multiview_flags_range[] = {
{ "none", { sizeof (uint32_t), &multiview_flags[0] } },
{ "right-view-first", { sizeof (uint32_t), &multiview_flags[1] } },
{ "left-flipped", { sizeof (uint32_t), &multiview_flags[2] } },
{ "left-flopped", { sizeof (uint32_t), &multiview_flags[3] } },
{ "right-flipped", { sizeof (uint32_t), &multiview_flags[4] } },
{ "right-flopped", { sizeof (uint32_t), &multiview_flags[5] } },
{ "half-aspect", { sizeof (uint32_t), &multiview_flags[6] } },
{ "mixed-mono", { sizeof (uint32_t), &multiview_flags[7] } },
};
static const uint32_t chroma_sites[] = {
SPA_VIDEO_CHROMA_SITE_UNKNOWN,
SPA_VIDEO_CHROMA_SITE_NONE,
SPA_VIDEO_CHROMA_SITE_H_COSITED,
SPA_VIDEO_CHROMA_SITE_V_COSITED,
SPA_VIDEO_CHROMA_SITE_ALT_LINE,
};
static const SpaPropRangeInfo chroma_site_range[] = {
{ "unknown", { sizeof (uint32_t), &chroma_sites[0] } },
{ "none", { sizeof (uint32_t), &chroma_sites[1] } },
{ "h-cosited", { sizeof (uint32_t), &chroma_sites[2] } },
{ "v-cosited", { sizeof (uint32_t), &chroma_sites[3] } },
{ "alt-line", { sizeof (uint32_t), &chroma_sites[4] } }
};
static const uint32_t color_ranges[] = {
SPA_VIDEO_COLOR_RANGE_UNKNOWN,
SPA_VIDEO_COLOR_RANGE_0_255,
SPA_VIDEO_COLOR_RANGE_16_235
};
static const SpaPropRangeInfo color_range_range[] = {
{ "unknown", { sizeof (uint32_t), &color_ranges[0] } },
{ "0_255", { sizeof (uint32_t), &color_ranges[1] } },
{ "16_235", { sizeof (uint32_t), &color_ranges[2] } },
};
static const uint32_t color_matrices[] = {
SPA_VIDEO_COLOR_MATRIX_UNKNOWN,
SPA_VIDEO_COLOR_MATRIX_RGB,
SPA_VIDEO_COLOR_MATRIX_FCC,
SPA_VIDEO_COLOR_MATRIX_BT709,
SPA_VIDEO_COLOR_MATRIX_BT601,
SPA_VIDEO_COLOR_MATRIX_SMPTE240M,
SPA_VIDEO_COLOR_MATRIX_BT2020
};
static const SpaPropRangeInfo color_matrix_range[] = {
{ "unknown", { sizeof (uint32_t), &color_matrices[0] } },
{ "rgb", { sizeof (uint32_t), &color_matrices[1] } },
{ "fcc", { sizeof (uint32_t), &color_matrices[2] } },
{ "bt709", { sizeof (uint32_t), &color_matrices[3] } },
{ "bt601", { sizeof (uint32_t), &color_matrices[4] } },
{ "smpte240m", { sizeof (uint32_t), &color_matrices[5] } },
{ "bt2020", { sizeof (uint32_t), &color_matrices[6] } },
};
static const uint32_t transfer_functions[] = {
SPA_VIDEO_TRANSFER_UNKNOWN,
SPA_VIDEO_TRANSFER_GAMMA10,
SPA_VIDEO_TRANSFER_GAMMA18,
SPA_VIDEO_TRANSFER_GAMMA20,
SPA_VIDEO_TRANSFER_GAMMA22,
SPA_VIDEO_TRANSFER_BT709,
SPA_VIDEO_TRANSFER_SMPTE240M,
SPA_VIDEO_TRANSFER_SRGB,
SPA_VIDEO_TRANSFER_GAMMA28,
SPA_VIDEO_TRANSFER_LOG100,
SPA_VIDEO_TRANSFER_LOG316,
SPA_VIDEO_TRANSFER_BT2020_12,
SPA_VIDEO_TRANSFER_ADOBERGB
};
static const SpaPropRangeInfo transfer_function_range[] = {
{ "unknown", { sizeof (uint32_t), &transfer_functions[0] } },
{ "gamma10", { sizeof (uint32_t), &transfer_functions[1] } },
{ "gamma18", { sizeof (uint32_t), &transfer_functions[2] } },
{ "gamma20", { sizeof (uint32_t), &transfer_functions[3] } },
{ "gamma22", { sizeof (uint32_t), &transfer_functions[4] } },
{ "bt709", { sizeof (uint32_t), &transfer_functions[5] } },
{ "smpte240m", { sizeof (uint32_t), &transfer_functions[6] } },
{ "srgb", { sizeof (uint32_t), &transfer_functions[7] } },
{ "gamma28", { sizeof (uint32_t), &transfer_functions[8] } },
{ "log100", { sizeof (uint32_t), &transfer_functions[9] } },
{ "log316", { sizeof (uint32_t), &transfer_functions[10] } },
{ "bt2020_12", { sizeof (uint32_t), &transfer_functions[11] } },
{ "adobergb", { sizeof (uint32_t), &transfer_functions[12] } },
};
static const uint32_t color_primaries[] = {
SPA_VIDEO_COLOR_PRIMARIES_UNKNOWN,
SPA_VIDEO_COLOR_PRIMARIES_BT709,
SPA_VIDEO_COLOR_PRIMARIES_BT470M,
SPA_VIDEO_COLOR_PRIMARIES_BT470BG,
SPA_VIDEO_COLOR_PRIMARIES_SMPTE170M,
SPA_VIDEO_COLOR_PRIMARIES_SMPTE240M,
SPA_VIDEO_COLOR_PRIMARIES_FILM,
SPA_VIDEO_COLOR_PRIMARIES_BT2020,
SPA_VIDEO_COLOR_PRIMARIES_ADOBERGB
};
static const SpaPropRangeInfo color_primaries_range[] = {
{ "unknown", { sizeof (uint32_t), &color_primaries[0] } },
{ "bt709", { sizeof (uint32_t), &color_primaries[1] } },
{ "bt470M", { sizeof (uint32_t), &color_primaries[2] } },
{ "bt470BG", { sizeof (uint32_t), &color_primaries[3] } },
{ "smpte170m", { sizeof (uint32_t), &color_primaries[4] } },
{ "smpte240m", { sizeof (uint32_t), &color_primaries[5] } },
{ "film", { sizeof (uint32_t), &color_primaries[6] } },
{ "bt2020", { sizeof (uint32_t), &color_primaries[7] } },
{ "adobergb", { sizeof (uint32_t), &color_primaries[8] } },
};
static const uint32_t min_uint32 = 1;
static const uint32_t max_uint32 = UINT32_MAX;
static const SpaPropRangeInfo uint32_range[] = {
{ "min", { sizeof (uint32_t), &min_uint32 } },
{ "max", { sizeof (uint32_t), &max_uint32 } },
};
static const SpaFraction min_framerate = { 0, 1 };
static const SpaFraction max_framerate = { UINT32_MAX, 1 };
static const SpaPropRangeInfo framerate_range[] = {
{ "min", { sizeof (SpaFraction), &min_framerate } },
{ "max", { sizeof (SpaFraction), &max_framerate } },
};
static const SpaPropInfo format_prop_info[] =
static const ParseInfo *
parse_info_find (const ParseInfo *info, uint32_t key, uint32_t type)
{
{ SPA_PROP_ID_VIDEO_INFO, 0,
"info",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL | SPA_PROP_FLAG_INFO,
SPA_PROP_TYPE_POINTER, sizeof (SpaVideoInfoRaw),
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
NULL },
{ SPA_PROP_ID_VIDEO_FORMAT, 0,
"format",
SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_range), format_range,
NULL },
{ SPA_PROP_ID_VIDEO_SIZE, 0,
"size",
SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_RECTANGLE, sizeof (SpaRectangle),
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, size_range,
NULL },
{ SPA_PROP_ID_VIDEO_FRAMERATE, 0,
"framerate",
SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
NULL },
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, 0,
"max-framerate",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
NULL },
{ SPA_PROP_ID_VIDEO_VIEWS, 0,
"views",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
NULL },
{ SPA_PROP_ID_VIDEO_INTERLACE_MODE, 0,
"interlace-mode",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (interlace_mode_range), interlace_mode_range,
NULL },
{ SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, 0,
"pixel-aspect-ratio",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
NULL },
{ SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, 0,
"multiview-mode",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (multiview_mode_range), multiview_mode_range,
NULL },
{ SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, 0,
"multiview-flags",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (multiview_flags_range), multiview_flags_range,
NULL },
{ SPA_PROP_ID_VIDEO_CHROMA_SITE, 0,
"chroma-site",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (chroma_site_range), chroma_site_range,
NULL },
{ SPA_PROP_ID_VIDEO_COLOR_RANGE, 0,
"color-range",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_range_range), color_range_range,
NULL },
{ SPA_PROP_ID_VIDEO_COLOR_MATRIX, 0,
"color-matrix",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_matrix_range), color_matrix_range,
NULL },
{ SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, 0,
"transfer-function",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (transfer_function_range), transfer_function_range,
NULL },
{ SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, 0,
"color-primaries",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_primaries_range), color_primaries_range,
NULL },
};
SpaResult
spa_prop_info_fill_video (SpaPropInfo *info,
SpaPropIdVideo id,
size_t offset)
{
int i;
if (info == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
i = id - SPA_PROP_ID_MEDIA_CUSTOM_START;
if (i < 0 || i >= SPA_N_ELEMENTS (format_prop_info))
return SPA_RESULT_INVALID_PROPERTY_INDEX;
memcpy (info, &format_prop_info[i], sizeof (SpaPropInfo));
info->offset = offset - sizeof (SpaFormat) + sizeof (SpaProps);
return SPA_RESULT_OK;
while (info->key) {
if (info->key == key && info->type == type)
return info;
info++;
}
return NULL;
}
SpaResult
spa_format_video_init (SpaMediaType type,
SpaMediaSubType subtype,
SpaFormatVideo *format)
spa_format_video_parse (const SpaFormat *format,
SpaVideoInfo *info)
{
SpaPropInfo *prop_info = NULL;
unsigned int n_prop_info = 0;
int i;
SpaPODProp *prop;
const ParseInfo *pinfo, *find;
if (type != SPA_MEDIA_TYPE_VIDEO)
return SPA_RESULT_INVALID_ARGUMENTS;
if (format->media_type != SPA_MEDIA_TYPE_VIDEO)
return SPA_RESULT_INVALID_MEDIA_TYPE;
switch (subtype) {
switch (format->media_subtype) {
case SPA_MEDIA_SUBTYPE_RAW:
{
static SpaPropInfo raw_prop_info[] = {
{ SPA_PROP_ID_VIDEO_INFO, offsetof (SpaFormatVideo, info.raw) },
{ SPA_PROP_ID_VIDEO_FORMAT, offsetof (SpaFormatVideo, info.raw.format) },
{ SPA_PROP_ID_VIDEO_SIZE, offsetof (SpaFormatVideo, info.raw.size) },
{ SPA_PROP_ID_VIDEO_FRAMERATE, offsetof (SpaFormatVideo, info.raw.framerate) },
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, offsetof (SpaFormatVideo, info.raw.max_framerate) },
{ SPA_PROP_ID_VIDEO_VIEWS, offsetof (SpaFormatVideo, info.raw.views) },
{ SPA_PROP_ID_VIDEO_INTERLACE_MODE, offsetof (SpaFormatVideo, info.raw.interlace_mode) },
{ SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, offsetof (SpaFormatVideo, info.raw.pixel_aspect_ratio) },
{ SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, offsetof (SpaFormatVideo, info.raw.multiview_mode) },
{ SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, offsetof (SpaFormatVideo, info.raw.multiview_flags) },
{ SPA_PROP_ID_VIDEO_CHROMA_SITE, offsetof (SpaFormatVideo, info.raw.chroma_site) },
{ SPA_PROP_ID_VIDEO_COLOR_RANGE, offsetof (SpaFormatVideo, info.raw.color_range) },
{ SPA_PROP_ID_VIDEO_COLOR_MATRIX, offsetof (SpaFormatVideo, info.raw.color_matrix) },
{ SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, offsetof (SpaFormatVideo, info.raw.transfer_function) },
{ SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, offsetof (SpaFormatVideo, info.raw.color_primaries) },
};
static const SpaVideoInfoRaw default_raw_info = {
SPA_VIDEO_FORMAT_UNKNOWN,
{ 320, 240 },
{ 25, 1 },
{ 25, 1 },
1,
SPA_VIDEO_INTERLACE_MODE_PROGRESSIVE,
{ 1, 1},
SPA_VIDEO_MULTIVIEW_MODE_MONO,
SPA_VIDEO_MULTIVIEW_FLAGS_NONE,
SPA_VIDEO_CHROMA_SITE_UNKNOWN,
SPA_VIDEO_COLOR_RANGE_UNKNOWN,
SPA_VIDEO_COLOR_MATRIX_UNKNOWN,
SPA_VIDEO_TRANSFER_UNKNOWN,
SPA_VIDEO_COLOR_PRIMARIES_UNKNOWN
};
prop_info = raw_prop_info;
n_prop_info = SPA_N_ELEMENTS (raw_prop_info);
format->format.props.unset_mask = (1 << 15)-2;
format->info.raw = default_raw_info;
pinfo = raw_parse_info;
break;
}
case SPA_MEDIA_SUBTYPE_H264:
{
static SpaPropInfo h264_prop_info[] = {
{ SPA_PROP_ID_VIDEO_INFO, offsetof (SpaFormatVideo, info.h264) },
{ SPA_PROP_ID_VIDEO_SIZE, offsetof (SpaFormatVideo, info.h264.size) },
{ SPA_PROP_ID_VIDEO_FRAMERATE, offsetof (SpaFormatVideo, info.h264.framerate) },
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, offsetof (SpaFormatVideo, info.h264.max_framerate) },
};
static const SpaVideoInfoH264 default_h264_info = {
{ 320, 240 },
{ 25, 1 },
{ 25, 1 }
};
prop_info = h264_prop_info;
n_prop_info = SPA_N_ELEMENTS (h264_prop_info);
format->format.props.unset_mask = (1 << 4)-2;
format->info.h264 = default_h264_info;
pinfo = h264_parse_info;
break;
}
case SPA_MEDIA_SUBTYPE_MJPG:
{
static SpaPropInfo mjpg_prop_info[] = {
{ SPA_PROP_ID_VIDEO_INFO, offsetof (SpaFormatVideo, info.mjpg) },
{ SPA_PROP_ID_VIDEO_SIZE, offsetof (SpaFormatVideo, info.mjpg.size) },
{ SPA_PROP_ID_VIDEO_FRAMERATE, offsetof (SpaFormatVideo, info.mjpg.framerate) },
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, offsetof (SpaFormatVideo, info.mjpg.max_framerate) },
};
static const SpaVideoInfoMJPG default_mjpg_info = {
{ 320, 240 },
{ 25, 1 },
{ 25, 1 }
};
prop_info = mjpg_prop_info;
n_prop_info = SPA_N_ELEMENTS (mjpg_prop_info);
format->format.props.unset_mask = (1 << 4)-2;
format->info.mjpg = default_mjpg_info;
pinfo = mjpg_parse_info;
break;
}
case SPA_MEDIA_SUBTYPE_DV:
case SPA_MEDIA_SUBTYPE_MPEGTS:
case SPA_MEDIA_SUBTYPE_H263:
@ -587,76 +116,29 @@ spa_format_video_init (SpaMediaType type,
return SPA_RESULT_INVALID_ARGUMENTS;
}
if (prop_info && prop_info[0].name == NULL) {
for (i = 0; i < n_prop_info; i++)
spa_prop_info_fill_video (&prop_info[i],
prop_info[i].id,
prop_info[i].offset);
info->media_type = format->media_type;
info->media_subtype = format->media_subtype;
SPA_POD_OBJECT_BODY_FOREACH (&format->obj.body, format->obj.pod.size, prop) {
if ((find = parse_info_find (pinfo, prop->body.key, prop->body.value.type))) {
memcpy (SPA_MEMBER (info, find->offset, void),
SPA_POD_BODY (&prop->body.value),
SPA_POD_BODY_SIZE (&prop->body.value));
}
}
format->format.media_type = type;
format->format.media_subtype = subtype;
format->format.props.n_prop_info = n_prop_info;
format->format.props.prop_info = prop_info;
return SPA_RESULT_OK;
}
SpaResult
spa_format_video_parse (const SpaFormat *format,
SpaFormatVideo *vformat)
{
SpaPropValue value;
const SpaProps *props;
SpaResult res;
unsigned int idx;
if ((void *)format == (void *)vformat)
return SPA_RESULT_OK;
if (format->media_type != SPA_MEDIA_TYPE_VIDEO)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if ((res = spa_format_video_init (format->media_type,
format->media_subtype,
vformat)) < 0)
return res;
props = &format->props;
idx = spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_INFO);
if ((res = spa_props_get_value (props, idx, &value)) < 0)
goto fallback;
if (props->prop_info[idx].type != SPA_PROP_TYPE_POINTER)
goto fallback;
memcpy (&vformat->info, value.value, SPA_MIN (value.size, sizeof (vformat->info)));
vformat->format.props.unset_mask = props->unset_mask;
return SPA_RESULT_OK;
fallback:
res = spa_props_copy_values (props, &vformat->format.props);
return res;
}
static void
prop_finish (SpaPropBuilder *b)
{
b->dest = malloc (b->size);
}
SpaResult
spa_format_filter (const SpaFormat *format,
const SpaFormat *filter,
SpaFormat **result)
SpaPODBuilder *result)
{
SpaPropBuilder b;
SpaResult res;
if (format == NULL || result == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
if (filter == NULL) {
*result = (SpaFormat *) format;
spa_pod_builder_raw (result, format, SPA_FORMAT_SIZE (format), true);
return SPA_RESULT_OK;
}
@ -664,36 +146,7 @@ spa_format_filter (const SpaFormat *format,
filter->media_subtype != format->media_subtype)
return SPA_RESULT_INVALID_MEDIA_TYPE;
spa_prop_builder_init (&b, sizeof (SpaFormatVideo), offsetof(SpaFormatVideo, format.props));
b.finish = prop_finish;
if ((res = spa_props_filter (&b, &format->props, &filter->props)) != SPA_RESULT_OK)
return res;
spa_pod_builder_raw (result, format, SPA_FORMAT_SIZE (format), true);
*result = b.dest;
(*result)->media_type = format->media_type;
(*result)->media_subtype = format->media_subtype;
return res;
}
SpaResult
spa_format_video_builder_add (SpaPropBuilder *b,
SpaPropBuilderInfo *info,
SpaPropIdVideo id,
size_t offset)
{
spa_prop_info_fill_video (&info->info, id, offset);
spa_prop_builder_add_info (b, info);
return SPA_RESULT_OK;
}
SpaResult
spa_format_video_builder_add_range (SpaPropBuilder *b,
SpaPropBuilderRange *range,
int index)
{
range->info = b->info->info.range_values[index];
spa_prop_builder_add_range (b, range);
return SPA_RESULT_OK;
}

View file

@ -1,43 +0,0 @@
/* Simple Plugin API
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __SPA_LIBVIDEO_RAW_H__
#define __SPA_LIBVIDEO_RAW_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <lib/prop-builder.h>
SpaResult spa_format_video_builder_add (SpaPropBuilder *b,
SpaPropBuilderInfo *info,
SpaPropIdVideo id,
size_t offset);
SpaResult spa_format_video_builder_add_range (SpaPropBuilder *b,
SpaPropBuilderRange *range,
int index);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __SPA_LIBVIDEO_RAW_H__ */