format: make media types and properties dynamic

Use URI properties to dynamically register the media types/subtypes and
property names. Add some helpers to set up the mappings.
This commit is contained in:
Wim Taymans 2017-03-21 11:28:23 +01:00
parent ee470fc6c6
commit 3f5a3e215b
25 changed files with 769 additions and 685 deletions

View file

@ -29,19 +29,41 @@ extern "C" {
typedef struct _SpaAudioInfo SpaAudioInfo;
typedef enum {
SPA_PROP_ID_AUDIO_INFO = SPA_PROP_ID_MEDIA_CUSTOM_START,
SPA_PROP_ID_AUDIO_FORMAT,
SPA_PROP_ID_AUDIO_FLAGS,
SPA_PROP_ID_AUDIO_LAYOUT,
SPA_PROP_ID_AUDIO_RATE,
SPA_PROP_ID_AUDIO_CHANNELS,
SPA_PROP_ID_AUDIO_CHANNEL_MASK,
} SpaPropIdAudio;
#define SPA_PROP_AUDIO_URI "http://spaplug.in/ns/prop-audio"
#define SPA_PROP_AUDIO_PREFIX SPA_PROP_AUDIO_URI "#"
#define SPA_PROP_AUDIO__format SPA_PROP_AUDIO_PREFIX "format"
#define SPA_PROP_AUDIO__flags SPA_PROP_AUDIO_PREFIX "flags"
#define SPA_PROP_AUDIO__layout SPA_PROP_AUDIO_PREFIX "layout"
#define SPA_PROP_AUDIO__rate SPA_PROP_AUDIO_PREFIX "rate"
#define SPA_PROP_AUDIO__channels SPA_PROP_AUDIO_PREFIX "channels"
#define SPA_PROP_AUDIO__channelMask SPA_PROP_AUDIO_PREFIX "channel-mask"
typedef struct {
uint32_t format;
uint32_t flags;
uint32_t layout;
uint32_t rate;
uint32_t channels;
uint32_t channel_mask;
} SpaPropAudio;
static inline void
spa_prop_audio_map (SpaIDMap *map, SpaPropAudio *types)
{
if (types->format == 0) {
types->format = spa_id_map_get_id (map, SPA_PROP_AUDIO__format);
types->flags = spa_id_map_get_id (map, SPA_PROP_AUDIO__flags);
types->layout = spa_id_map_get_id (map, SPA_PROP_AUDIO__layout);
types->rate = spa_id_map_get_id (map, SPA_PROP_AUDIO__rate);
types->channels = spa_id_map_get_id (map, SPA_PROP_AUDIO__channels);
types->channel_mask = spa_id_map_get_id (map, SPA_PROP_AUDIO__channelMask);
}
}
struct _SpaAudioInfo {
SpaMediaType media_type;
SpaMediaSubType media_subtype;
uint32_t media_type;
uint32_t media_subtype;
union {
SpaAudioInfoRaw raw;
} info;

View file

@ -37,16 +37,16 @@ spa_pod_builder_push_format (SpaPODBuilder *builder,
{
const SpaFormat p = { { sizeof (SpaFormatBody), SPA_POD_TYPE_OBJECT },
{ { 0, 0 },
{ { sizeof (uint32_t), SPA_POD_TYPE_INT }, media_type },
{ { sizeof (uint32_t), SPA_POD_TYPE_INT }, media_subtype } } };
{ { sizeof (uint32_t), SPA_POD_TYPE_URI }, media_type },
{ { sizeof (uint32_t), SPA_POD_TYPE_URI }, media_subtype } } };
return spa_pod_builder_push (builder, frame, &p.pod,
spa_pod_builder_raw (builder, &p, sizeof(p)));
}
#define spa_pod_builder_format(b,f,media_type,media_subtype,...) \
spa_pod_builder_object(b, f, 0, 0, \
SPA_POD_TYPE_INT,media_type, \
SPA_POD_TYPE_INT,media_subtype, \
SPA_POD_TYPE_URI,media_type, \
SPA_POD_TYPE_URI,media_subtype, \
__VA_ARGS__)
SpaResult

View file

@ -33,66 +33,152 @@ typedef struct _SpaFormat SpaFormat;
#include <spa/defs.h>
#include <spa/pod-utils.h>
#include <spa/id-map.h>
typedef enum {
SPA_MEDIA_TYPE_INVALID = 0,
SPA_MEDIA_TYPE_AUDIO = 1,
SPA_MEDIA_TYPE_VIDEO = 2,
SPA_MEDIA_TYPE_IMAGE = 3,
} SpaMediaType;
#define SPA_MEDIA_TYPE_URI "http://spaplug.in/ns/media-type"
#define SPA_MEDIA_TYPE_PREFIX SPA_MEDIA_TYPE_URI "#"
typedef enum {
SPA_MEDIA_SUBTYPE_INVALID = 0,
#define SPA_MEDIA_TYPE__audio SPA_MEDIA_TYPE_PREFIX "audio"
#define SPA_MEDIA_TYPE__video SPA_MEDIA_TYPE_PREFIX "video"
#define SPA_MEDIA_TYPE__image SPA_MEDIA_TYPE_PREFIX "image"
#define SPA_MEDIA_SUBTYPE_ANY_FIRST 1
SPA_MEDIA_SUBTYPE_RAW = SPA_MEDIA_SUBTYPE_ANY_FIRST,
#define SPA_MEDIA_SUBTYPE_ANY_LAST SPA_MEDIA_SUBTYPE_RAW
typedef struct {
uint32_t audio;
uint32_t video;
uint32_t image;
} SpaMediaTypes;
/* VIDEO */
#define SPA_MEDIA_SUBTYPE_VIDEO_FIRST 20
SPA_MEDIA_SUBTYPE_H264 = SPA_MEDIA_SUBTYPE_VIDEO_FIRST,
SPA_MEDIA_SUBTYPE_MJPG,
SPA_MEDIA_SUBTYPE_DV,
SPA_MEDIA_SUBTYPE_MPEGTS,
SPA_MEDIA_SUBTYPE_H263,
SPA_MEDIA_SUBTYPE_MPEG1,
SPA_MEDIA_SUBTYPE_MPEG2,
SPA_MEDIA_SUBTYPE_MPEG4,
SPA_MEDIA_SUBTYPE_XVID,
SPA_MEDIA_SUBTYPE_VC1,
SPA_MEDIA_SUBTYPE_VP8,
SPA_MEDIA_SUBTYPE_VP9,
SPA_MEDIA_SUBTYPE_JPEG,
SPA_MEDIA_SUBTYPE_BAYER,
#define SPA_MEDIA_SUBTYPE_VIDEO_LAST SPA_MEDIA_SUBTYPE_BAYER
static inline void
spa_media_types_fill (SpaMediaTypes *types, SpaIDMap *map)
{
if (types->audio == 0) {
types->audio = spa_id_map_get_id (map, SPA_MEDIA_TYPE__audio);
types->video = spa_id_map_get_id (map, SPA_MEDIA_TYPE__video);
types->image = spa_id_map_get_id (map, SPA_MEDIA_TYPE__image);
}
}
/* AUDIO */
#define SPA_MEDIA_SUBTYPE_AUDIO_FIRST 200
SPA_MEDIA_SUBTYPE_MP3 = SPA_MEDIA_SUBTYPE_AUDIO_FIRST,
SPA_MEDIA_SUBTYPE_AAC,
SPA_MEDIA_SUBTYPE_VORBIS,
SPA_MEDIA_SUBTYPE_WMA,
SPA_MEDIA_SUBTYPE_RA,
SPA_MEDIA_SUBTYPE_SBC,
SPA_MEDIA_SUBTYPE_ADPCM,
SPA_MEDIA_SUBTYPE_G723,
SPA_MEDIA_SUBTYPE_G726,
SPA_MEDIA_SUBTYPE_G729,
SPA_MEDIA_SUBTYPE_AMR,
SPA_MEDIA_SUBTYPE_GSM,
#define SPA_MEDIA_SUBTYPE_AUDIO_LAST SPA_MEDIA_SUBTYPE_GSM
#define SPA_MEDIA_SUBTYPE_URI "http://spaplug.in/ns/media-subtype"
#define SPA_MEDIA_SUBTYPE_PREFIX SPA_MEDIA_TYPE_URI "#"
} SpaMediaSubType;
#define SPA_MEDIA_SUBTYPE__raw SPA_MEDIA_TYPE_PREFIX "raw"
typedef enum {
SPA_PROP_ID_INVALID = 0,
SPA_PROP_ID_MEDIA_CUSTOM_START = 200,
} SpaFormatProps;
typedef struct {
uint32_t raw;
} SpaMediaSubtypes;
static inline void
spa_media_subtypes_map (SpaIDMap *map, SpaMediaSubtypes *types)
{
if (types->raw == 0) {
types->raw = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__raw);
}
}
#define SPA_MEDIA_SUBTYPE__h264 SPA_MEDIA_SUBTYPE_PREFIX "h264"
#define SPA_MEDIA_SUBTYPE__mjpg SPA_MEDIA_SUBTYPE_PREFIX "mjpg"
#define SPA_MEDIA_SUBTYPE__dv SPA_MEDIA_SUBTYPE_PREFIX "dv"
#define SPA_MEDIA_SUBTYPE__mpegts SPA_MEDIA_SUBTYPE_PREFIX "mpegts"
#define SPA_MEDIA_SUBTYPE__h263 SPA_MEDIA_SUBTYPE_PREFIX "h263"
#define SPA_MEDIA_SUBTYPE__mpeg1 SPA_MEDIA_SUBTYPE_PREFIX "mpeg1"
#define SPA_MEDIA_SUBTYPE__mpeg2 SPA_MEDIA_SUBTYPE_PREFIX "mpeg2"
#define SPA_MEDIA_SUBTYPE__mpeg4 SPA_MEDIA_SUBTYPE_PREFIX "mpeg4"
#define SPA_MEDIA_SUBTYPE__xvid SPA_MEDIA_SUBTYPE_PREFIX "xvid"
#define SPA_MEDIA_SUBTYPE__vc1 SPA_MEDIA_SUBTYPE_PREFIX "vc1"
#define SPA_MEDIA_SUBTYPE__vp8 SPA_MEDIA_SUBTYPE_PREFIX "vp8"
#define SPA_MEDIA_SUBTYPE__vp9 SPA_MEDIA_SUBTYPE_PREFIX "vp9"
#define SPA_MEDIA_SUBTYPE__jpeg SPA_MEDIA_SUBTYPE_PREFIX "jpeg"
#define SPA_MEDIA_SUBTYPE__bayer SPA_MEDIA_SUBTYPE_PREFIX "bayer"
typedef struct {
uint32_t h264;
uint32_t mjpg;
uint32_t dv;
uint32_t mpegts;
uint32_t h263;
uint32_t mpeg1;
uint32_t mpeg2;
uint32_t mpeg4;
uint32_t xvid;
uint32_t vc1;
uint32_t vp8;
uint32_t vp9;
uint32_t jpeg;
uint32_t bayer;
} SpaMediaSubtypesVideo;
static inline void
spa_media_subtypes_video_map (SpaIDMap *map, SpaMediaSubtypesVideo *types)
{
if (types->h264 == 0) {
types->h264 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__h264);
types->mjpg = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__mjpg);
types->dv = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__dv);
types->mpegts = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__mpegts);
types->h263 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__h263);
types->mpeg1 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__mpeg1);
types->mpeg2 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__mpeg2);
types->mpeg4 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__mpeg4);
types->xvid = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__xvid);
types->vc1 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__vc1);
types->vp8 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__vp8);
types->vp9 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__vp9);
types->jpeg = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__jpeg);
types->bayer = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__bayer);
}
}
#define SPA_MEDIA_SUBTYPE__mp3 SPA_MEDIA_SUBTYPE_PREFIX "mp3"
#define SPA_MEDIA_SUBTYPE__aac SPA_MEDIA_SUBTYPE_PREFIX "aac"
#define SPA_MEDIA_SUBTYPE__vorbis SPA_MEDIA_SUBTYPE_PREFIX "vorbis"
#define SPA_MEDIA_SUBTYPE__wma SPA_MEDIA_SUBTYPE_PREFIX "wma"
#define SPA_MEDIA_SUBTYPE__ra SPA_MEDIA_SUBTYPE_PREFIX "ra"
#define SPA_MEDIA_SUBTYPE__sbc SPA_MEDIA_SUBTYPE_PREFIX "sbc"
#define SPA_MEDIA_SUBTYPE__adpcm SPA_MEDIA_SUBTYPE_PREFIX "adpcm"
#define SPA_MEDIA_SUBTYPE__g723 SPA_MEDIA_SUBTYPE_PREFIX "g723"
#define SPA_MEDIA_SUBTYPE__g726 SPA_MEDIA_SUBTYPE_PREFIX "g726"
#define SPA_MEDIA_SUBTYPE__g729 SPA_MEDIA_SUBTYPE_PREFIX "g729"
#define SPA_MEDIA_SUBTYPE__amr SPA_MEDIA_SUBTYPE_PREFIX "amr"
#define SPA_MEDIA_SUBTYPE__gsm SPA_MEDIA_SUBTYPE_PREFIX "gsm"
typedef struct {
uint32_t mp3;
uint32_t aac;
uint32_t vorbis;
uint32_t wma;
uint32_t ra;
uint32_t sbc;
uint32_t adpcm;
uint32_t g723;
uint32_t g726;
uint32_t g729;
uint32_t amr;
uint32_t gsm;
} SpaMediaSubtypesAudio;
static inline void
spa_media_subtypes_audio_map (SpaIDMap *map, SpaMediaSubtypesAudio *types)
{
if (types->mp3 == 0) {
types->mp3 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__mp3);
types->aac = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__aac);
types->vorbis = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__vorbis);
types->wma = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__wma);
types->ra = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__ra);
types->sbc = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__sbc);
types->adpcm = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__adpcm);
types->g723 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__g723);
types->g726 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__g726);
types->g729 = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__g729);
types->amr = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__amr);
types->gsm = spa_id_map_get_id (map, SPA_MEDIA_SUBTYPE__gsm);
}
}
typedef struct {
SpaPODObjectBody obj_body;
SpaPODInt media_type SPA_ALIGNED (8);
SpaPODInt media_subtype SPA_ALIGNED (8);
SpaPODURI media_type SPA_ALIGNED (8);
SpaPODURI media_subtype SPA_ALIGNED (8);
/* contents follow, series of SpaPODProp */
} SpaFormatBody;
@ -110,8 +196,8 @@ struct _SpaFormat {
#define SPA_FORMAT_INIT(size,type,media_type,media_subtype,...) \
{ { size, SPA_POD_TYPE_OBJECT }, \
{ { 0, type }, \
SPA_POD_INT_INIT (media_type), \
SPA_POD_INT_INIT (media_subtype) } }
SPA_POD_URI_INIT (media_type), \
SPA_POD_URI_INIT (media_subtype) } }
#define SPA_FORMAT_BODY_FOREACH(body, size, iter) \
for ((iter) = SPA_MEMBER ((body), sizeof (SpaFormatBody), SpaPODProp); \

View file

@ -341,30 +341,18 @@ spa_pod_builder_addv (SpaPODBuilder *builder,
uint32_t body_size;
static const uint64_t zeroes = 0;
while (type != 0) {
while (type != SPA_POD_TYPE_INVALID) {
SpaPODFrame *f = NULL;
const void *data[3];
uint32_t size[3], ref, i, n_sizes = 0;
switch (type) {
case SPA_POD_TYPE_INVALID:
case SPA_POD_TYPE_NONE:
break;
case SPA_POD_TYPE_BOOL:
head.bool_pod.pod.type = SPA_POD_TYPE_BOOL;
head.bool_pod.pod.size = body_size = sizeof (uint32_t);
head.bool_pod.value = va_arg (args, int);
head_size = sizeof (SpaPOD);
body = &head.bool_pod.value;
goto primitive;
case SPA_POD_TYPE_URI:
head.uri_pod.pod.type = SPA_POD_TYPE_URI;
head.uri_pod.pod.size = body_size = sizeof (uint32_t);
head.uri_pod.value = va_arg (args, int);
head_size = sizeof (SpaPOD);
body = &head.uri_pod.value;
goto primitive;
case SPA_POD_TYPE_INT:
head.int_pod.pod.type = SPA_POD_TYPE_INT;
head.int_pod.pod.type = type;
head.int_pod.pod.size = body_size = sizeof (uint32_t);
head.int_pod.value = va_arg (args, int);
head_size = sizeof (SpaPOD);

View file

@ -36,6 +36,7 @@ extern "C" {
*/
typedef enum {
SPA_POD_TYPE_INVALID = 0,
SPA_POD_TYPE_NONE = 1,
SPA_POD_TYPE_BOOL,
SPA_POD_TYPE_URI,
SPA_POD_TYPE_INT,

View file

@ -30,34 +30,80 @@ extern "C" {
typedef struct _SpaVideoInfo SpaVideoInfo;
typedef enum {
SPA_PROP_ID_VIDEO_INFO = SPA_PROP_ID_MEDIA_CUSTOM_START,
SPA_PROP_ID_VIDEO_FORMAT,
SPA_PROP_ID_VIDEO_SIZE,
SPA_PROP_ID_VIDEO_FRAMERATE,
SPA_PROP_ID_VIDEO_MAX_FRAMERATE,
SPA_PROP_ID_VIDEO_VIEWS,
SPA_PROP_ID_VIDEO_INTERLACE_MODE,
SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO,
SPA_PROP_ID_VIDEO_MULTIVIEW_MODE,
SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS,
SPA_PROP_ID_VIDEO_CHROMA_SITE,
SPA_PROP_ID_VIDEO_COLOR_RANGE,
SPA_PROP_ID_VIDEO_COLOR_MATRIX,
SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION,
SPA_PROP_ID_VIDEO_COLOR_PRIMARIES,
SPA_PROP_ID_VIDEO_PROFILE,
SPA_PROP_ID_VIDEO_LEVEL,
SPA_PROP_ID_VIDEO_STREAM_FORMAT,
SPA_PROP_ID_VIDEO_ALIGNMENT,
} SpaPropIdVideo;
#define SPA_PROP_VIDEO_URI "http://spaplug.in/ns/prop-video"
#define SPA_PROP_VIDEO_PREFIX SPA_PROP_VIDEO_URI "#"
#define SPA_PROP_VIDEO__format SPA_PROP_VIDEO_PREFIX "format"
#define SPA_PROP_VIDEO__size SPA_PROP_VIDEO_PREFIX "size"
#define SPA_PROP_VIDEO__framerate SPA_PROP_VIDEO_PREFIX "framerate"
#define SPA_PROP_VIDEO__maxFramerate SPA_PROP_VIDEO_PREFIX "max-framerate"
#define SPA_PROP_VIDEO__views SPA_PROP_VIDEO_PREFIX "views"
#define SPA_PROP_VIDEO__interlaceMode SPA_PROP_VIDEO_PREFIX "interlace-mode"
#define SPA_PROP_VIDEO__pixelAspectRatio SPA_PROP_VIDEO_PREFIX "pixel-aspect-ratio"
#define SPA_PROP_VIDEO__multiviewMode SPA_PROP_VIDEO_PREFIX "multiview-mode"
#define SPA_PROP_VIDEO__multiviewFlags SPA_PROP_VIDEO_PREFIX "multiview-flags"
#define SPA_PROP_VIDEO__chromaSite SPA_PROP_VIDEO_PREFIX "chroma-site"
#define SPA_PROP_VIDEO__colorRange SPA_PROP_VIDEO_PREFIX "color-range"
#define SPA_PROP_VIDEO__colorMatrix SPA_PROP_VIDEO_PREFIX "color-matrix"
#define SPA_PROP_VIDEO__transferFunction SPA_PROP_VIDEO_PREFIX "transfer-function"
#define SPA_PROP_VIDEO__colorPrimaries SPA_PROP_VIDEO_PREFIX "color-primaries"
#define SPA_PROP_VIDEO__profile SPA_PROP_VIDEO_PREFIX "profile"
#define SPA_PROP_VIDEO__level SPA_PROP_VIDEO_PREFIX "level"
#define SPA_PROP_VIDEO__streamFormat SPA_PROP_VIDEO_PREFIX "stream-format"
#define SPA_PROP_VIDEO__alignment SPA_PROP_VIDEO_PREFIX "alignment"
typedef struct {
uint32_t format;
uint32_t size;
uint32_t framerate;
uint32_t max_framerate;
uint32_t views;
uint32_t interlace_mode;
uint32_t pixel_aspect_ratio;
uint32_t multiview_mode;
uint32_t multiview_flags;
uint32_t chroma_site;
uint32_t color_range;
uint32_t color_matrix;
uint32_t transfer_function;
uint32_t color_primaries;
uint32_t profile;
uint32_t level;
uint32_t stream_format;
uint32_t alignment;
} SpaPropVideo;
static inline void
spa_prop_video_map (SpaIDMap *map, SpaPropVideo *types)
{
if (types->format == 0) {
types->format = spa_id_map_get_id (map, SPA_PROP_VIDEO__format);
types->size = spa_id_map_get_id (map, SPA_PROP_VIDEO__size);
types->framerate = spa_id_map_get_id (map, SPA_PROP_VIDEO__framerate);
types->max_framerate = spa_id_map_get_id (map, SPA_PROP_VIDEO__maxFramerate);
types->views = spa_id_map_get_id (map, SPA_PROP_VIDEO__views);
types->interlace_mode = spa_id_map_get_id (map, SPA_PROP_VIDEO__interlaceMode);
types->pixel_aspect_ratio = spa_id_map_get_id (map, SPA_PROP_VIDEO__pixelAspectRatio);
types->multiview_mode = spa_id_map_get_id (map, SPA_PROP_VIDEO__multiviewMode);
types->multiview_flags = spa_id_map_get_id (map, SPA_PROP_VIDEO__multiviewFlags);
types->chroma_site = spa_id_map_get_id (map, SPA_PROP_VIDEO__chromaSite);
types->color_range = spa_id_map_get_id (map, SPA_PROP_VIDEO__colorRange);
types->color_matrix = spa_id_map_get_id (map, SPA_PROP_VIDEO__colorMatrix);
types->transfer_function = spa_id_map_get_id (map, SPA_PROP_VIDEO__transferFunction);
types->color_primaries = spa_id_map_get_id (map, SPA_PROP_VIDEO__colorPrimaries);
types->profile = spa_id_map_get_id (map, SPA_PROP_VIDEO__profile);
types->level = spa_id_map_get_id (map, SPA_PROP_VIDEO__level);
types->stream_format = spa_id_map_get_id (map, SPA_PROP_VIDEO__streamFormat);
types->alignment = spa_id_map_get_id (map, SPA_PROP_VIDEO__alignment);
}
}
SpaResult spa_format_video_parse (const SpaFormat *format,
SpaVideoInfo *info);
struct _SpaVideoInfo {
SpaMediaType media_type;
SpaMediaSubType media_subtype;
uint32_t media_type;
uint32_t media_subtype;
union {
SpaVideoInfoRaw raw;
SpaVideoInfoH264 h264;