From 16b62de53ab3d7d7e5b73bffe1eb06af9243bf3c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 24 Feb 2017 09:28:18 +0100 Subject: [PATCH] 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 --- pinos/client/serialize.c | 18 +- pinos/gst/gstpinosformat.c | 11 +- pinos/gst/gstpinosformat.h | 2 +- pinos/server/core.c | 1 + pinos/server/link.c | 9 +- pinos/tools/pinos-monitor.c | 1 + spa/include/spa/audio/format.h | 18 +- spa/include/spa/format-builder.h | 179 +++++++ spa/include/spa/format.h | 37 +- spa/include/spa/pod-builder.h | 93 ++-- spa/include/spa/pod.h | 18 +- spa/include/spa/video/format.h | 16 +- spa/lib/audio-raw.c | 306 ++--------- spa/lib/debug.c | 370 +++++++------ spa/lib/debug.h | 2 + spa/lib/video-raw.c | 681 +++--------------------- spa/lib/video-raw.h | 43 -- spa/plugins/alsa/alsa-sink.c | 44 +- spa/plugins/alsa/alsa-source.c | 42 +- spa/plugins/alsa/alsa-utils.c | 2 +- spa/plugins/alsa/alsa-utils.h | 8 +- spa/plugins/audiomixer/audiomixer.c | 11 +- spa/plugins/audiotestsrc/audiotestsrc.c | 58 +- spa/plugins/ffmpeg/ffmpeg-dec.c | 24 +- spa/plugins/ffmpeg/ffmpeg-enc.c | 16 +- spa/plugins/v4l2/v4l2-source.c | 110 ++-- spa/plugins/v4l2/v4l2-utils.c | 282 +++++----- spa/plugins/videotestsrc/draw.c | 6 +- spa/plugins/videotestsrc/videotestsrc.c | 76 ++- spa/plugins/volume/volume.c | 38 +- spa/plugins/xv/xv-sink.c | 30 +- spa/plugins/xv/xv-utils.c | 2 +- spa/tests/test-props.c | 110 +++- spa/tests/test-props2.c | 11 +- 34 files changed, 1096 insertions(+), 1579 deletions(-) create mode 100644 spa/include/spa/format-builder.h delete mode 100644 spa/lib/video-raw.h diff --git a/pinos/client/serialize.c b/pinos/client/serialize.c index 43f890481..182a5de5b 100644 --- a/pinos/client/serialize.c +++ b/pinos/client/serialize.c @@ -95,24 +95,19 @@ pinos_serialize_format_get_size (const SpaFormat *format) if (format == NULL) return 0; - return pinos_serialize_props_get_size (&format->props) - sizeof (SpaProps) + sizeof (SpaFormat); + return SPA_FORMAT_SIZE (format); } size_t pinos_serialize_format_serialize (void *dest, const SpaFormat *format) { - SpaFormat *tf; size_t size; if (format == NULL) return 0; - tf = dest; - tf->media_type = format->media_type; - tf->media_subtype = format->media_subtype; - - dest = SPA_MEMBER (tf, offsetof (SpaFormat, props), void); - size = pinos_serialize_props_serialize (dest, &format->props) - sizeof (SpaProps) + sizeof (SpaFormat); + size = SPA_FORMAT_SIZE (format); + memcpy (dest, format, size); return size; } @@ -120,12 +115,7 @@ pinos_serialize_format_serialize (void *dest, const SpaFormat *format) SpaFormat * pinos_serialize_format_deserialize (void *src, off_t offset) { - SpaFormat *f; - - f = SPA_MEMBER (src, offset, SpaFormat); - pinos_serialize_props_deserialize (f, offsetof (SpaFormat, props)); - - return f; + return SPA_MEMBER (src, offset, SpaFormat); } SpaFormat * diff --git a/pinos/gst/gstpinosformat.c b/pinos/gst/gstpinosformat.c index 8ea009da0..10957ab3d 100644 --- a/pinos/gst/gstpinosformat.c +++ b/pinos/gst/gstpinosformat.c @@ -29,6 +29,7 @@ #include "gstpinosformat.h" +#if 0 static guint calc_range_size (const GValue *val) { @@ -278,10 +279,12 @@ handle_video_framerate (ConvertData *d) d->pi++; } } +#endif static SpaFormat * convert_1 (GstCapsFeatures *cf, GstStructure *cs) { +#if 0 const GValue *val; guint size, n_infos = 0, n_ranges = 0, n_datas = 0; ConvertData d; @@ -425,6 +428,8 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs) handle_video_framerate (&d); } return d.f; +#endif + return NULL; } SpaFormat * @@ -471,12 +476,12 @@ gst_caps_to_format_all (GstCaps *caps) } GstCaps * -gst_caps_from_format (SpaFormat *format) +gst_caps_from_format (const SpaFormat *format) { GstCaps *res = NULL; if (format->media_type == SPA_MEDIA_TYPE_VIDEO) { - SpaFormatVideo f; + SpaVideoInfo f; if (spa_format_video_parse (format, &f) < 0) return NULL; @@ -506,7 +511,7 @@ gst_caps_from_format (SpaFormat *format) NULL); } } else if (format->media_type == SPA_MEDIA_TYPE_AUDIO) { - SpaFormatAudio f; + SpaAudioInfo f; if (spa_format_audio_parse (format, &f) < 0) return NULL; diff --git a/pinos/gst/gstpinosformat.h b/pinos/gst/gstpinosformat.h index 62e57f1ac..11219f5d9 100644 --- a/pinos/gst/gstpinosformat.h +++ b/pinos/gst/gstpinosformat.h @@ -29,7 +29,7 @@ G_BEGIN_DECLS SpaFormat * gst_caps_to_format (GstCaps *caps, guint index); GPtrArray * gst_caps_to_format_all (GstCaps *caps); -GstCaps * gst_caps_from_format (SpaFormat *format); +GstCaps * gst_caps_from_format (const SpaFormat *format); G_END_DECLS diff --git a/pinos/server/core.c b/pinos/server/core.c index f3aa05f79..a58042471 100644 --- a/pinos/server/core.c +++ b/pinos/server/core.c @@ -22,6 +22,7 @@ #include #include #include +#include typedef struct { PinosGlobal this; diff --git a/pinos/server/link.c b/pinos/server/link.c index 470fb62e4..b2f3f5bdc 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -59,9 +59,10 @@ pinos_link_update_state (PinosLink *link, PinosLinkState old = link->state; if (state != old) { - pinos_log_debug ("link %p: update state %s -> %s", link, + pinos_log_debug ("link %p: update state %s -> %s (%s)", link, pinos_link_state_as_string (old), - pinos_link_state_as_string (state)); + pinos_link_state_as_string (state), + error); link->state = state; if (link->error) @@ -97,8 +98,10 @@ do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) 0, NULL, &error); - if (format == NULL) + if (format == NULL) { + asprintf (&error, "no common format found"); goto error; + } pinos_log_debug ("link %p: doing set format", this); if (pinos_log_level_enabled (SPA_LOG_LEVEL_DEBUG)) diff --git a/pinos/tools/pinos-monitor.c b/pinos/tools/pinos-monitor.c index b4c7463d8..d0029d9ea 100644 --- a/pinos/tools/pinos-monitor.c +++ b/pinos/tools/pinos-monitor.c @@ -21,6 +21,7 @@ #include #include +#include typedef struct { bool running; diff --git a/spa/include/spa/audio/format.h b/spa/include/spa/audio/format.h index 2acd566be..8b1d68fa2 100644 --- a/spa/include/spa/audio/format.h +++ b/spa/include/spa/audio/format.h @@ -27,7 +27,7 @@ extern "C" { #include #include -typedef struct _SpaFormatAudio SpaFormatAudio; +typedef struct _SpaAudioInfo SpaAudioInfo; typedef enum { SPA_PROP_ID_AUDIO_INFO = SPA_PROP_ID_MEDIA_CUSTOM_START, @@ -39,24 +39,16 @@ typedef enum { SPA_PROP_ID_AUDIO_CHANNEL_MASK, } SpaPropIdAudio; -SpaResult spa_prop_info_fill_audio (SpaPropInfo *info, - SpaPropIdAudio id, - size_t offset); - -struct _SpaFormatAudio { - SpaFormat format; +struct _SpaAudioInfo { + SpaMediaType media_type; + SpaMediaSubType media_subtype; union { SpaAudioInfoRaw raw; } info; }; -SpaResult spa_format_audio_init (SpaMediaType type, - SpaMediaSubType subtype, - SpaFormatAudio *format); SpaResult spa_format_audio_parse (const SpaFormat *format, - SpaFormatAudio *aformat); -SpaResult spa_format_audio_filter (SpaFormatAudio *format, - const SpaFormat *filter); + SpaAudioInfo *info); #ifdef __cplusplus } /* extern "C" */ diff --git a/spa/include/spa/format-builder.h b/spa/include/spa/format-builder.h new file mode 100644 index 000000000..e42fdd53f --- /dev/null +++ b/spa/include/spa/format-builder.h @@ -0,0 +1,179 @@ +/* Simple Plugin API + * Copyright (C) 2016 Wim Taymans + * + * 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_FORMAT_BUILDER_H__ +#define __SPA_FORMAT_BUILDER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include + +static inline off_t +spa_pod_builder_push_format (SpaPODBuilder *builder, + SpaPODFrame *frame, + uint32_t media_type, + uint32_t media_subtype) +{ + SpaFormat f = { media_type, media_subtype, { { 0, 0 }, { 0, 0 } } }; + off_t offset; + + offset = spa_pod_builder_raw (builder, &f, sizeof(f) - sizeof(SpaPODObject), false); + if (spa_pod_builder_push_object (builder, frame, 0, 0) == -1) + offset = -1; + return offset; +} + +static inline void +spa_pod_builder_format_propv (SpaPODBuilder *builder, + uint32_t propid, + va_list args) +{ + while (propid != 0) { + int type, n_alternatives = -1; + SpaPODProp *prop = NULL; + SpaPODFrame f; + off_t off; + + if ((off = spa_pod_builder_push_prop (builder, &f, propid, SPA_POD_PROP_FLAG_READWRITE)) != -1) + prop = SPA_MEMBER (builder->data, off, SpaPODProp); + + type = va_arg (args, uint32_t); + + while (n_alternatives != 0) { + switch (type) { + case SPA_POD_TYPE_INVALID: + break; + case SPA_POD_TYPE_BOOL: + spa_pod_builder_bool (builder, va_arg (args, int)); + break; + case SPA_POD_TYPE_INT: + spa_pod_builder_int (builder, va_arg (args, int32_t)); + break; + case SPA_POD_TYPE_LONG: + spa_pod_builder_long (builder, va_arg (args, int64_t)); + break; + case SPA_POD_TYPE_FLOAT: + spa_pod_builder_float (builder, va_arg (args, double)); + break; + case SPA_POD_TYPE_DOUBLE: + spa_pod_builder_double (builder, va_arg (args, double)); + break; + case SPA_POD_TYPE_STRING: + { + const char *str = va_arg (args, char *); + uint32_t len = va_arg (args, uint32_t); + spa_pod_builder_string (builder, str, len); + break; + } + case SPA_POD_TYPE_RECTANGLE: + { + uint32_t width = va_arg (args, uint32_t), height = va_arg (args, uint32_t); + spa_pod_builder_rectangle (builder, width, height); + break; + } + case SPA_POD_TYPE_FRACTION: + { + uint32_t num = va_arg (args, uint32_t), denom = va_arg (args, uint32_t); + spa_pod_builder_fraction (builder, num, denom); + break; + } + case SPA_POD_TYPE_BITMASK: + break; + case SPA_POD_TYPE_ARRAY: + case SPA_POD_TYPE_STRUCT: + case SPA_POD_TYPE_OBJECT: + case SPA_POD_TYPE_PROP: + break; + } + if (n_alternatives == -1) { + uint32_t flags = va_arg (args, uint32_t); + if (prop) + prop->body.flags = flags; + + switch (flags & SPA_POD_PROP_RANGE_MASK) { + case SPA_POD_PROP_RANGE_NONE: + n_alternatives = 0; + break; + case SPA_POD_PROP_RANGE_MIN_MAX: + n_alternatives = 2; + break; + case SPA_POD_PROP_RANGE_STEP: + n_alternatives = 3; + break; + case SPA_POD_PROP_RANGE_ENUM: + case SPA_POD_PROP_RANGE_MASK: + n_alternatives = va_arg (args, int); + break; + } + } else + n_alternatives--; + } + spa_pod_builder_pop (builder, &f); + + propid = va_arg (args, uint32_t); + } +} + +static inline void +spa_pod_builder_format_prop (SpaPODBuilder *builder, + uint32_t propid, ...) +{ + va_list args; + + va_start (args, propid); + spa_pod_builder_format_propv (builder, propid, args); + va_end (args); +} + +static inline off_t +spa_pod_builder_format (SpaPODBuilder *builder, + uint32_t media_type, + uint32_t media_subtype, + uint32_t propid, ...) +{ + SpaPODFrame f; + va_list args; + off_t off; + + off = spa_pod_builder_push_format (builder, &f, media_type, media_subtype); + + va_start (args, propid); + spa_pod_builder_format_propv (builder, propid, args); + va_end (args); + + spa_pod_builder_pop (builder, &f); + + return off; +} + +SpaResult +spa_format_filter (const SpaFormat *format, + const SpaFormat *filter, + SpaPODBuilder *result); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __SPA_FORMAT_BUILDER_H__ */ diff --git a/spa/include/spa/format.h b/spa/include/spa/format.h index d794bf780..df1552112 100644 --- a/spa/include/spa/format.h +++ b/spa/include/spa/format.h @@ -26,8 +26,10 @@ extern "C" { typedef struct _SpaFormat SpaFormat; +#include + #include -#include +#include typedef enum { SPA_MEDIA_TYPE_INVALID = 0, @@ -36,7 +38,6 @@ typedef enum { SPA_MEDIA_TYPE_IMAGE = 3, } SpaMediaType; - typedef enum { SPA_MEDIA_SUBTYPE_INVALID = 0, @@ -80,41 +81,33 @@ typedef enum { } SpaMediaSubType; -/** - * SpaFormat: - * @media_type: media type - * @media_subtype: subtype - * @props: properties - */ -struct _SpaFormat { - SpaMediaType media_type; - SpaMediaSubType media_subtype; - SpaProps props; -}; - typedef enum { SPA_PROP_ID_INVALID = 0, SPA_PROP_ID_MEDIA_CUSTOM_START = 200, } SpaFormatProps; +/** + * SpaFormat: + * @media_type: media type + * @media_subtype: subtype + * @pod: POD object with properties + */ +struct _SpaFormat { + uint32_t media_type; + uint32_t media_subtype; + SpaPODObject obj; +}; - +#define SPA_FORMAT_SIZE(f) (sizeof(SpaFormat) + (f)->obj.pod.size) static inline SpaResult spa_format_fixate (SpaFormat *format) { if (format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; - - format->props.unset_mask = 0; return SPA_RESULT_OK; } -SpaResult -spa_format_filter (const SpaFormat *format, - const SpaFormat *filter, - SpaFormat **result); - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/include/spa/pod-builder.h b/spa/include/spa/pod-builder.h index 83c7ae207..c046d55f9 100644 --- a/spa/include/spa/pod-builder.h +++ b/spa/include/spa/pod-builder.h @@ -24,34 +24,30 @@ extern "C" { #endif -typedef struct _SpaPodFrame { - struct _SpaPodFrame *parent; - off_t offset; +#include + +typedef struct _SpaPODFrame { + struct _SpaPODFrame *parent; + SpaPOD pod; + off_t ref; } SpaPODFrame; -typedef struct { +typedef struct _SpaPODBuilder { void *data; size_t size; off_t offset; SpaPODFrame *stack; + off_t (*write) (struct _SpaPODBuilder *builder, off_t ref, const void *data, size_t size); } SpaPODBuilder; -static inline uint32_t -spa_pod_builder_top (SpaPODBuilder *builder) -{ - if (builder->stack && builder->stack->offset != -1) - return SPA_MEMBER(builder->data, builder->stack->offset, SpaPOD)->type; - return SPA_POD_TYPE_INVALID; -} - static inline bool spa_pod_builder_in_array (SpaPODBuilder *builder) { - if (builder->stack && builder->stack->offset != -1) { - SpaPOD *p = SPA_MEMBER(builder->data, builder->stack->offset, SpaPOD); - if (p->type == SPA_POD_TYPE_ARRAY && p->size > 0) + SpaPODFrame *f; + if ((f = builder->stack)) { + if (f->pod.type == SPA_POD_TYPE_ARRAY && f->pod.size > 0) return true; - if (p->type == SPA_POD_TYPE_PROP && p->size > (sizeof (SpaPODPropBody) - sizeof(SpaPOD))) + if (f->pod.type == SPA_POD_TYPE_PROP && f->pod.size > (sizeof (SpaPODPropBody) - sizeof(SpaPOD))) return true; } return false; @@ -60,12 +56,14 @@ spa_pod_builder_in_array (SpaPODBuilder *builder) static inline off_t spa_pod_builder_push (SpaPODBuilder *builder, SpaPODFrame *frame, - off_t offset) + const SpaPOD *pod, + off_t ref) { frame->parent = builder->stack; - frame->offset = offset; + frame->pod = *pod; + frame->ref = ref; builder->stack = frame; - return offset; + return ref; } static inline void @@ -73,14 +71,13 @@ spa_pod_builder_advance (SpaPODBuilder *builder, uint32_t size, bool pad) { SpaPODFrame *f; - if (pad) { + if (pad) size += SPA_ROUND_UP_N (builder->offset, 8) - builder->offset; - } - builder->offset += size; - for (f = builder->stack; f; f = f->parent) { - if (f->offset != -1) - SPA_MEMBER (builder->data, f->offset, SpaPOD)->size += size; + if (size > 0) { + builder->offset += size; + for (f = builder->stack; f; f = f->parent) + f->pod.size += size; } } @@ -88,6 +85,12 @@ static inline void spa_pod_builder_pop (SpaPODBuilder *builder, SpaPODFrame *frame) { + if (frame->ref != -1) { + if (builder->write) + builder->write (builder, frame->ref, &frame->pod, sizeof(SpaPOD)); + else + memcpy (builder->data + frame->ref, &frame->pod, sizeof(SpaPOD)); + } builder->stack = frame->parent; spa_pod_builder_advance (builder, 0, true); } @@ -95,16 +98,20 @@ spa_pod_builder_pop (SpaPODBuilder *builder, static inline off_t spa_pod_builder_raw (SpaPODBuilder *builder, const void *data, uint32_t size, bool pad) { - off_t offset = builder->offset; - - if (offset + size <= builder->size) - memcpy (builder->data + offset, data, size); - else - offset = -1; + off_t ref; + if (builder->write) { + ref = builder->write (builder, -1, data, size); + } else { + ref = builder->offset; + if (ref + size > builder->size) + ref = -1; + else + memcpy (builder->data + ref, data, size); + } spa_pod_builder_advance (builder, size, pad); - return offset; + return ref; } static inline off_t @@ -190,16 +197,16 @@ spa_pod_builder_string (SpaPODBuilder *builder, const char *str, uint32_t len) } static inline off_t -spa_pod_builder_rectangle (SpaPODBuilder *builder, SpaRectangle *val) +spa_pod_builder_rectangle (SpaPODBuilder *builder, uint32_t width, uint32_t height) { - const SpaPODRectangle p = { { sizeof (val), SPA_POD_TYPE_RECTANGLE }, *val }; + const SpaPODRectangle p = { { sizeof (SpaRectangle), SPA_POD_TYPE_RECTANGLE }, { width, height } }; return spa_pod_builder_primitive (builder, &p.pod); } static inline off_t -spa_pod_builder_fraction (SpaPODBuilder *builder, SpaFraction *val) +spa_pod_builder_fraction (SpaPODBuilder *builder, uint32_t num, uint32_t denom) { - const SpaPODFraction p = { { sizeof (val), SPA_POD_TYPE_FRACTION }, *val }; + const SpaPODFraction p = { { sizeof (SpaFraction), SPA_POD_TYPE_FRACTION }, { num, denom } }; return spa_pod_builder_primitive (builder, &p.pod); } @@ -208,7 +215,8 @@ spa_pod_builder_push_array (SpaPODBuilder *builder, SpaPODFrame *frame) { const SpaPODArray p = { { sizeof (SpaPODArrayBody) - sizeof (SpaPOD), SPA_POD_TYPE_ARRAY }, { { 0, 0 } } }; - return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false)); + return spa_pod_builder_push (builder, frame, &p.pod, + spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false)); } static inline off_t @@ -216,7 +224,7 @@ spa_pod_builder_array (SpaPODBuilder *builder, uint32_t child_size, uint32_t child_type, uint32_t n_elems, - const void* elems) + const void *elems) { const SpaPODArray p = { { (uint32_t)(sizeof (SpaPODArrayBody) + n_elems * child_size), SPA_POD_TYPE_ARRAY }, @@ -233,7 +241,8 @@ spa_pod_builder_push_struct (SpaPODBuilder *builder, SpaPODFrame *frame) { const SpaPODStruct p = { { 0, SPA_POD_TYPE_STRUCT } }; - return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p), false)); + return spa_pod_builder_push (builder, frame, &p.pod, + spa_pod_builder_raw (builder, &p, sizeof(p), false)); } static inline off_t @@ -243,7 +252,8 @@ spa_pod_builder_push_object (SpaPODBuilder *builder, uint32_t type) { const SpaPODObject p = { { sizeof (SpaPODObjectBody), SPA_POD_TYPE_OBJECT }, { id, type } }; - return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p), false)); + return spa_pod_builder_push (builder, frame, &p.pod, + spa_pod_builder_raw (builder, &p, sizeof(p), false)); } static inline off_t @@ -254,7 +264,8 @@ spa_pod_builder_push_prop (SpaPODBuilder *builder, { const SpaPODProp p = { { sizeof (SpaPODPropBody) - sizeof(SpaPOD), SPA_POD_TYPE_PROP}, { key, flags | SPA_POD_PROP_RANGE_NONE, { 0, 0 } } }; - return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false)); + return spa_pod_builder_push (builder, frame, &p.pod, + spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false)); } #ifdef __cplusplus diff --git a/spa/include/spa/pod.h b/spa/include/spa/pod.h index 0b0254bee..b9b5c5719 100644 --- a/spa/include/spa/pod.h +++ b/spa/include/spa/pod.h @@ -46,7 +46,8 @@ typedef enum { SPA_POD_TYPE_ARRAY, SPA_POD_TYPE_STRUCT, SPA_POD_TYPE_OBJECT, - SPA_POD_TYPE_PROP + SPA_POD_TYPE_PROP, + SPA_POD_TYPE_BYTES } SpaPODType; typedef struct { @@ -122,17 +123,18 @@ typedef struct { typedef struct { uint32_t key; +#define SPA_POD_PROP_RANGE_NONE 0 +#define SPA_POD_PROP_RANGE_MIN_MAX 1 +#define SPA_POD_PROP_RANGE_STEP 2 +#define SPA_POD_PROP_RANGE_ENUM 3 +#define SPA_POD_PROP_RANGE_FLAGS 4 +#define SPA_POD_PROP_RANGE_MASK 0xf #define SPA_POD_PROP_FLAG_UNSET (1 << 4) #define SPA_POD_PROP_FLAG_OPTIONAL (1 << 5) #define SPA_POD_PROP_FLAG_READABLE (1 << 6) #define SPA_POD_PROP_FLAG_WRITABLE (1 << 7) #define SPA_POD_PROP_FLAG_READWRITE (SPA_POD_PROP_FLAG_READABLE | SPA_POD_PROP_FLAG_WRITABLE) #define SPA_POD_PROP_FLAG_DEPRECATED (1 << 8) -#define SPA_POD_PROP_RANGE_NONE 0 -#define SPA_POD_PROP_RANGE_MIN_MAX 1 -#define SPA_POD_PROP_RANGE_STEP 2 -#define SPA_POD_PROP_RANGE_ENUM 3 -#define SPA_POD_PROP_RANGE_FLAGS 4 uint32_t flags; SpaPOD value; /* array with elements of value.size follows, @@ -144,6 +146,8 @@ typedef struct { SpaPODPropBody body; } SpaPODProp; +#define SPA_POD_PROP_N_VALUES(prop) (((prop)->pod.size - sizeof (SpaPODPropBody)) / (prop)->body.value.size) + typedef struct { uint32_t id; uint32_t type; @@ -176,7 +180,7 @@ typedef struct { (iter) = SPA_MEMBER ((iter), (body)->value.size, __typeof__(*iter))) static inline SpaPODProp * -spa_pod_object_body_find_prop (SpaPODObjectBody *body, uint32_t size, uint32_t key) +spa_pod_object_body_find_prop (const SpaPODObjectBody *body, uint32_t size, uint32_t key) { SpaPODProp *res; SPA_POD_OBJECT_BODY_FOREACH (body, size, res) { diff --git a/spa/include/spa/video/format.h b/spa/include/spa/video/format.h index b1f97f850..e6c0df0dd 100644 --- a/spa/include/spa/video/format.h +++ b/spa/include/spa/video/format.h @@ -28,7 +28,7 @@ extern "C" { #include #include -typedef struct _SpaFormatVideo SpaFormatVideo; +typedef struct _SpaVideoInfo SpaVideoInfo; typedef enum { SPA_PROP_ID_VIDEO_INFO = SPA_PROP_ID_MEDIA_CUSTOM_START, @@ -52,18 +52,12 @@ typedef enum { SPA_PROP_ID_VIDEO_ALIGNMENT, } SpaPropIdVideo; -SpaResult spa_prop_info_fill_video (SpaPropInfo *info, - SpaPropIdVideo id, - size_t offset); - -SpaResult spa_format_video_init (SpaMediaType type, - SpaMediaSubType subtype, - SpaFormatVideo *format); SpaResult spa_format_video_parse (const SpaFormat *format, - SpaFormatVideo *dest); + SpaVideoInfo *info); -struct _SpaFormatVideo { - SpaFormat format; +struct _SpaVideoInfo { + SpaMediaType media_type; + SpaMediaSubType media_subtype; union { SpaVideoInfoRaw raw; SpaVideoInfoH264 h264; diff --git a/spa/lib/audio-raw.c b/spa/lib/audio-raw.c index c0d110a84..0956bda95 100644 --- a/spa/lib/audio-raw.c +++ b/spa/lib/audio-raw.c @@ -24,216 +24,49 @@ #include #include -#include -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; -} diff --git a/spa/lib/debug.c b/spa/lib/debug.c index 408619e68..3c2e6022f 100644 --- a/spa/lib/debug.c +++ b/spa/lib/debug.c @@ -20,9 +20,8 @@ #include #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"); } diff --git a/spa/lib/debug.h b/spa/lib/debug.h index 552248a69..cfae3b3e2 100644 --- a/spa/lib/debug.h +++ b/spa/lib/debug.h @@ -27,12 +27,14 @@ extern "C" { #include #include #include +#include #include #include #include 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); diff --git a/spa/lib/video-raw.c b/spa/lib/video-raw.c index 910c72012..a7d82bb99 100644 --- a/spa/lib/video-raw.c +++ b/spa/lib/video-raw.c @@ -24,551 +24,80 @@ #include #include +#include -#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; } diff --git a/spa/lib/video-raw.h b/spa/lib/video-raw.h deleted file mode 100644 index 6d408990f..000000000 --- a/spa/lib/video-raw.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Simple Plugin API - * Copyright (C) 2016 Wim Taymans - * - * 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 - -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__ */ diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-sink.c index 03b90b996..f369ff257 100644 --- a/spa/plugins/alsa/alsa-sink.c +++ b/spa/plugins/alsa/alsa-sink.c @@ -330,6 +330,10 @@ spa_alsa_sink_node_port_enum_formats (SpaNode *node, unsigned int index) { SpaALSASink *this; + SpaResult res; + SpaFormat *fmt; + uint8_t buffer[1024]; + SpaPODBuilder b = { buffer, sizeof (buffer), }; if (node == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -341,19 +345,43 @@ spa_alsa_sink_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO, - SPA_MEDIA_SUBTYPE_RAW, - &this->query_format); + fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b, + SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW, + SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT, + SPA_AUDIO_FORMAT_S16, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_ENUM, 2, + SPA_AUDIO_FORMAT_S16, + SPA_AUDIO_FORMAT_S32, + SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT, + 44100, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_MIN_MAX, + 1, INT32_MAX, + SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT, + 2, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_MIN_MAX, + 1, INT32_MAX, + 0), SpaFormat); break; case 1: - spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO, - SPA_MEDIA_SUBTYPE_AAC, - &this->query_format); + fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b, + SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_AAC, + 0), SpaFormat); break; default: return SPA_RESULT_ENUM_END; } - *format = &this->query_format.format; + + b.data = this->format_buffer; + b.size = sizeof (this->format_buffer); + b.offset = 0; + + if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK) + return res; + + *format = SPA_MEMBER (b.data, 0, SpaFormat); return SPA_RESULT_OK; } @@ -456,7 +484,7 @@ spa_alsa_sink_node_port_get_format (SpaNode *node, if (!this->have_format) return SPA_RESULT_NO_FORMAT; - *format = &this->current_format.format; + *format = NULL; return SPA_RESULT_OK; } diff --git a/spa/plugins/alsa/alsa-source.c b/spa/plugins/alsa/alsa-source.c index 20440f60c..3f0443587 100644 --- a/spa/plugins/alsa/alsa-source.c +++ b/spa/plugins/alsa/alsa-source.c @@ -367,6 +367,9 @@ spa_alsa_source_node_port_enum_formats (SpaNode *node, { SpaALSASource *this; SpaResult res; + SpaFormat *fmt; + uint8_t buffer[256]; + SpaPODBuilder b = { buffer, sizeof (buffer), }; if (node == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -378,23 +381,42 @@ spa_alsa_source_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO, - SPA_MEDIA_SUBTYPE_RAW, - &this->query_format); + fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b, + SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW, + SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT, + SPA_AUDIO_FORMAT_S16, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_ENUM, 2, + SPA_AUDIO_FORMAT_S16, + SPA_AUDIO_FORMAT_S32, + SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT, + 44100, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_MIN_MAX, + 1, INT32_MAX, + SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT, + 2, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_MIN_MAX, + 1, INT32_MAX, + 0), SpaFormat); break; case 1: - spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO, - SPA_MEDIA_SUBTYPE_AAC, - &this->query_format); - break; + fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b, + SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_AAC, + 0), SpaFormat); default: return SPA_RESULT_ENUM_END; } - if ((res = spa_format_audio_filter (&this->query_format, filter)) != SPA_RESULT_OK) + b.data = this->format_buffer; + b.size = sizeof (this->format_buffer); + b.offset = 0; + + if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK) return res; - *format = &this->query_format.format; + *format = SPA_MEMBER (this->format_buffer, 0, SpaFormat); return SPA_RESULT_OK; } @@ -502,7 +524,7 @@ spa_alsa_source_node_port_get_format (SpaNode *node, if (!this->have_format) return SPA_RESULT_NO_FORMAT; - *format = &this->current_format.format; + *format = NULL; return SPA_RESULT_OK; } diff --git a/spa/plugins/alsa/alsa-utils.c b/spa/plugins/alsa/alsa-utils.c index 5f03ed635..5fc40a0d0 100644 --- a/spa/plugins/alsa/alsa-utils.c +++ b/spa/plugins/alsa/alsa-utils.c @@ -108,7 +108,7 @@ spa_alsa_format_to_alsa (SpaAudioFormat format) } int -spa_alsa_set_format (SpaALSAState *state, SpaFormatAudio *fmt, SpaPortFormatFlags flags) +spa_alsa_set_format (SpaALSAState *state, SpaAudioInfo *fmt, SpaPortFormatFlags flags) { unsigned int rrate, rchannels; snd_pcm_uframes_t period_size; diff --git a/spa/plugins/alsa/alsa-utils.h b/spa/plugins/alsa/alsa-utils.h index f084e8df1..25fb28852 100644 --- a/spa/plugins/alsa/alsa-utils.h +++ b/spa/plugins/alsa/alsa-utils.h @@ -35,6 +35,7 @@ extern "C" { #include #include #include +#include typedef struct _SpaALSAState SpaALSAState; typedef struct _SpaALSABuffer SpaALSABuffer; @@ -89,8 +90,9 @@ struct _SpaALSAState { snd_pcm_t *hndl; bool have_format; - SpaFormatAudio query_format; - SpaFormatAudio current_format; + SpaAudioInfo current_format; + uint8_t format_buffer[1024]; + snd_pcm_sframes_t buffer_frames; snd_pcm_sframes_t period_frames; snd_pcm_format_t format; @@ -125,7 +127,7 @@ struct _SpaALSAState { }; int spa_alsa_set_format (SpaALSAState *state, - SpaFormatAudio *fmt, + SpaAudioInfo *info, SpaPortFormatFlags flags); SpaResult spa_alsa_start (SpaALSAState *state, bool xrun_recover); diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index 954408154..ce7e1347b 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -51,7 +51,7 @@ struct _MixerBuffer { typedef struct { bool valid; bool have_format; - SpaFormatAudio format[2]; + SpaAudioInfo format; SpaAudioMixerPortProps props[2]; SpaPortInfo info; size_t buffer_index; @@ -328,14 +328,11 @@ spa_audiomixer_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO, - SPA_MEDIA_SUBTYPE_RAW, - &port->format[0]); break; default: return SPA_RESULT_ENUM_END; } - *format = &port->format[0].format; + *format = NULL; return SPA_RESULT_OK; } @@ -366,7 +363,7 @@ spa_audiomixer_node_port_set_format (SpaNode *node, return SPA_RESULT_OK; } - if ((res = spa_format_audio_parse (format, &port->format[1])) < 0) + if ((res = spa_format_audio_parse (format, &port->format)) < 0) return res; port->have_format = true; @@ -396,7 +393,7 @@ spa_audiomixer_node_port_get_format (SpaNode *node, if (!port->have_format) return SPA_RESULT_NO_FORMAT; - *format = &port->format[1].format; + *format = NULL; return SPA_RESULT_OK; } diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index f161face1..5f8e24744 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #define SAMPLES_TO_TIME(this,s) ((s) * SPA_NSEC_PER_SEC / (this)->current_format.info.raw.rate) @@ -88,8 +89,8 @@ struct _SpaAudioTestSrc { SpaPortOutput *output; bool have_format; - SpaFormatAudio query_format; - SpaFormatAudio current_format; + SpaAudioInfo current_format; + uint8_t format_buffer[1024]; size_t bpf; ATSBuffer buffers[MAX_BUFFERS]; @@ -469,6 +470,9 @@ spa_audiotestsrc_node_port_enum_formats (SpaNode *node, { SpaAudioTestSrc *this; SpaResult res; + SpaFormat *fmt; + uint8_t buffer[256]; + SpaPODBuilder b = { buffer, sizeof (buffer), }; if (node == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -480,17 +484,40 @@ spa_audiotestsrc_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO, - SPA_MEDIA_SUBTYPE_RAW, - &this->query_format); + { + fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b, + SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW, + SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT, + SPA_AUDIO_FORMAT_S16, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_ENUM, 2, + SPA_AUDIO_FORMAT_S16, + SPA_AUDIO_FORMAT_S32, + SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT, + 44100, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_MIN_MAX, + 1, INT32_MAX, + SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT, + 2, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_MIN_MAX, + 1, INT32_MAX, + 0), SpaFormat); break; + } default: return SPA_RESULT_ENUM_END; } - if ((res = spa_format_audio_filter (&this->query_format, filter)) != SPA_RESULT_OK) + + b.data = this->format_buffer; + b.size = sizeof (this->format_buffer); + b.offset = 0; + + if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK) return res; - *format = &this->query_format.format; + *format = SPA_MEMBER (this->format_buffer, 0, SpaFormat); return SPA_RESULT_OK; } @@ -569,6 +596,7 @@ spa_audiotestsrc_node_port_get_format (SpaNode *node, const SpaFormat **format) { SpaAudioTestSrc *this; + SpaPODBuilder b = { NULL, }; if (node == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -581,7 +609,21 @@ spa_audiotestsrc_node_port_get_format (SpaNode *node, if (!this->have_format) return SPA_RESULT_NO_FORMAT; - *format = &this->current_format.format; + b.data = this->format_buffer; + b.size = sizeof (this->format_buffer); + + *format = SPA_MEMBER (b.data, spa_pod_builder_format (&b, + SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW, + SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT, + this->current_format.info.raw.format, + SPA_POD_PROP_FLAG_READWRITE, + SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT, + this->current_format.info.raw.rate, + SPA_POD_PROP_FLAG_READWRITE, + SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT, + this->current_format.info.raw.channels, + SPA_POD_PROP_FLAG_READWRITE, + 0), SpaFormat); return SPA_RESULT_OK; } diff --git a/spa/plugins/ffmpeg/ffmpeg-dec.c b/spa/plugins/ffmpeg/ffmpeg-dec.c index 858e1034e..5c7680431 100644 --- a/spa/plugins/ffmpeg/ffmpeg-dec.c +++ b/spa/plugins/ffmpeg/ffmpeg-dec.c @@ -51,8 +51,9 @@ struct _FFMpegBuffer { }; typedef struct { - SpaFormatVideo format[2]; - SpaFormat *current_format; + bool have_format; + SpaVideoInfo query_format; + SpaVideoInfo current_format; bool have_buffers; FFMpegBuffer buffers[MAX_BUFFERS]; SpaPortInfo info; @@ -268,14 +269,11 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - spa_format_video_init (SPA_MEDIA_TYPE_VIDEO, - SPA_MEDIA_SUBTYPE_RAW, - &port->format[0]); break; default: return SPA_RESULT_ENUM_END; } - *format = &port->format[0].format; + *format = NULL; return SPA_RESULT_OK; } @@ -302,16 +300,16 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node, port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; if (format == NULL) { - port->current_format = NULL; + port->have_format = false; return SPA_RESULT_OK; } - if ((res = spa_format_video_parse (format, &port->format[0]) < 0)) + if ((res = spa_format_video_parse (format, &port->query_format) < 0)) return res; if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - memcpy (&port->format[1], &port->format[0], sizeof (SpaFormatVideo)); - port->current_format = &port->format[1].format; + memcpy (&port->current_format, &port->query_format, sizeof (SpaVideoInfo)); + port->have_format = true; } return SPA_RESULT_OK; @@ -336,10 +334,10 @@ spa_ffmpeg_dec_node_port_get_format (SpaNode *node, port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - if (port->current_format == NULL) + if (!port->have_format) return SPA_RESULT_NO_FORMAT; - *format = port->current_format; + *format = NULL; return SPA_RESULT_OK; } @@ -476,7 +474,7 @@ spa_ffmpeg_dec_node_process_output (SpaNode *node) if ((output = port->io) == NULL) return SPA_RESULT_ERROR; - if (port->current_format == NULL) { + if (!port->have_format) { output->status = SPA_RESULT_NO_FORMAT; return SPA_RESULT_ERROR; } diff --git a/spa/plugins/ffmpeg/ffmpeg-enc.c b/spa/plugins/ffmpeg/ffmpeg-enc.c index c371e738c..2c3ad903b 100644 --- a/spa/plugins/ffmpeg/ffmpeg-enc.c +++ b/spa/plugins/ffmpeg/ffmpeg-enc.c @@ -56,7 +56,7 @@ struct _FFMpegBuffer { }; typedef struct { - SpaFormatVideo format[2]; + SpaVideoInfo format[2]; SpaFormat *current_format; bool have_buffers; FFMpegBuffer buffers[MAX_BUFFERS]; @@ -273,14 +273,11 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - spa_format_video_init (SPA_MEDIA_TYPE_VIDEO, - SPA_MEDIA_SUBTYPE_RAW, - &port->format[0]); break; default: return SPA_RESULT_ENUM_END; } - *format = &port->format[0].format; + *format = NULL; return SPA_RESULT_OK; } @@ -310,16 +307,17 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node, port->current_format = NULL; return SPA_RESULT_OK; } - if ((res = spa_format_video_parse (format, &port->format[0]) < 0)) - return res; if (format->media_type != SPA_MEDIA_TYPE_VIDEO || format->media_subtype != SPA_MEDIA_SUBTYPE_RAW) return SPA_RESULT_INVALID_MEDIA_TYPE; + if ((res = spa_format_video_parse (format, &port->format[0]) < 0)) + return res; + if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - memcpy (&port->format[1], &port->format[0], sizeof (SpaFormatVideo)); - port->current_format = &port->format[1].format; + memcpy (&port->format[1], &port->format[0], sizeof (SpaVideoInfo)); + port->current_format = NULL; } return SPA_RESULT_OK; diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 0a3f88cdc..57d9ca516 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -63,23 +64,6 @@ struct _V4l2Buffer { struct v4l2_buffer v4l2_buffer; }; -typedef struct _V4l2Format V4l2Format; - -struct _V4l2Format { - SpaFormat fmt; - SpaVideoFormat format; - SpaRectangle size; - SpaFraction framerate; - SpaVideoInterlaceMode interlace_mode; - SpaVideoColorRange color_range; - SpaVideoColorMatrix color_matrix; - SpaVideoTransferFunction transfer_function; - SpaVideoColorPrimaries color_primaries; - SpaPropInfo infos[16]; - SpaPropRangeInfo ranges[16]; - SpaFraction framerates[16]; -}; - typedef struct { uint32_t node; uint32_t clock; @@ -99,8 +83,9 @@ typedef struct { struct v4l2_frmsizeenum frmsize; struct v4l2_frmivalenum frmival; - V4l2Format format[2]; - V4l2Format *current_format; + bool have_format; + SpaVideoInfo current_format; + uint8_t format_buffer[1024]; int fd; bool opened; @@ -357,7 +342,7 @@ spa_v4l2_source_node_send_command (SpaNode *node, SpaV4l2State *state = &this->state[0]; SpaResult res; - if (state->current_format == NULL) + if (!state->have_format) return SPA_RESULT_NO_FORMAT; if (state->n_buffers == 0) @@ -380,7 +365,7 @@ spa_v4l2_source_node_send_command (SpaNode *node, { SpaV4l2State *state = &this->state[0]; - if (state->current_format == NULL) + if (!state->have_format) return SPA_RESULT_NO_FORMAT; if (state->n_buffers == 0) @@ -483,28 +468,6 @@ spa_v4l2_source_node_remove_port (SpaNode *node, return SPA_RESULT_NOT_IMPLEMENTED; } -static SpaResult -spa_v4l2_format_init (V4l2Format *f, const SpaFormat *sf) -{ - f->fmt.props.n_prop_info = 3; - f->fmt.props.prop_info = f->infos; - - spa_prop_info_fill_video (&f->infos[0], - SPA_PROP_ID_VIDEO_FORMAT, - offsetof (V4l2Format, format)); - spa_prop_info_fill_video (&f->infos[1], - SPA_PROP_ID_VIDEO_SIZE, - offsetof (V4l2Format, size)); - spa_prop_info_fill_video (&f->infos[2], - SPA_PROP_ID_VIDEO_FRAMERATE, - offsetof (V4l2Format, framerate)); - - f->fmt.media_type = sf->media_type; - f->fmt.media_subtype = sf->media_subtype; - - return spa_props_copy_values (&sf->props, &f->fmt.props); -} - static SpaResult spa_v4l2_source_node_port_enum_formats (SpaNode *node, SpaDirection direction, @@ -539,7 +502,7 @@ spa_v4l2_source_node_port_set_format (SpaNode *node, SpaV4l2Source *this; SpaV4l2State *state; SpaResult res; - V4l2Format *f, *tf; + SpaVideoInfo info; if (node == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -555,43 +518,34 @@ spa_v4l2_source_node_port_set_format (SpaNode *node, spa_v4l2_stream_off (this); spa_v4l2_clear_buffers (this); spa_v4l2_close (this); - state->current_format = NULL; + state->have_format = false; update_state (this, SPA_NODE_STATE_CONFIGURE); return SPA_RESULT_OK; } - f = &state->format[0]; - tf = &state->format[1]; - - if ((SpaFormat*)f != format) { - if ((res = spa_v4l2_format_init (f, format)) < 0) + if ((res = spa_format_video_parse (format, &info)) < 0) return res; - } else { - f = (V4l2Format*)format; - } - if (state->current_format) { - if (f->fmt.media_type == state->current_format->fmt.media_type && - f->fmt.media_subtype == state->current_format->fmt.media_subtype && - f->format == state->current_format->format && - f->size.width == state->current_format->size.width && - f->size.height == state->current_format->size.height) + if (state->have_format) { + if (info.media_type == state->current_format.media_type && + info.media_subtype == state->current_format.media_subtype && + info.info.raw.format == state->current_format.info.raw.format && + info.info.raw.size.width == state->current_format.info.raw.size.width && + info.info.raw.size.height == state->current_format.info.raw.size.height) return SPA_RESULT_OK; if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { spa_v4l2_use_buffers (this, NULL, 0); - state->current_format = NULL; + state->have_format = false; } } - if (spa_v4l2_set_format (this, f, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0) + if (spa_v4l2_set_format (this, &info, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0) return SPA_RESULT_INVALID_MEDIA_TYPE; if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - if ((res = spa_v4l2_format_init (tf, &f->fmt)) < 0) - return res; - state->current_format = tf; - + state->current_format = info; + state->have_format = true; update_state (this, SPA_NODE_STATE_READY); } @@ -606,6 +560,7 @@ spa_v4l2_source_node_port_get_format (SpaNode *node, { SpaV4l2Source *this; SpaV4l2State *state; + SpaPODBuilder b = { NULL, }; if (node == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -617,10 +572,26 @@ spa_v4l2_source_node_port_get_format (SpaNode *node, state = &this->state[port_id]; - if (state->current_format == NULL) + if (!state->have_format) return SPA_RESULT_NO_FORMAT; - *format = &state->current_format->fmt; + b.data = state->format_buffer; + b.size = sizeof (state->format_buffer); + + *format = SPA_MEMBER (b.data, spa_pod_builder_format (&b, + SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW, + SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT, + state->current_format.info.raw.format, + SPA_POD_PROP_FLAG_READWRITE, + SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE, + state->current_format.info.raw.size.width, + state->current_format.info.raw.size.height, + SPA_POD_PROP_FLAG_READWRITE, + SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, + state->current_format.info.raw.framerate.num, + state->current_format.info.raw.framerate.denom, + SPA_POD_PROP_FLAG_READWRITE, + 0), SpaFormat); return SPA_RESULT_OK; } @@ -685,7 +656,7 @@ spa_v4l2_source_node_port_use_buffers (SpaNode *node, state = &this->state[port_id]; - if (state->current_format == NULL) + if (!state->have_format) return SPA_RESULT_NO_FORMAT; if (state->n_buffers) { @@ -728,7 +699,7 @@ spa_v4l2_source_node_port_alloc_buffers (SpaNode *node, state = &this->state[port_id]; - if (state->current_format == NULL) + if (!state->have_format) return SPA_RESULT_NO_FORMAT; res = spa_v4l2_alloc_buffers (this, params, n_params, buffers, n_buffers); @@ -1003,6 +974,7 @@ v4l2_source_init (const SpaHandleFactory *factory, strncpy (this->props[1].device, str, 63); this->props[1].props.unset_mask &= ~1; } + this->props[1].props.unset_mask &= ~1; update_state (this, SPA_NODE_STATE_CONFIGURE); diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index 12ff21da9..525e47001 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -328,27 +328,25 @@ enum_filter_format (const SpaFormat *filter, unsigned int index) if ((filter->media_type == SPA_MEDIA_TYPE_VIDEO || filter->media_type == SPA_MEDIA_TYPE_IMAGE)) { if (filter->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { - SpaPropValue val; - SpaResult res; - unsigned int idx; - const SpaPropInfo *pi; + SpaPODProp *p; + unsigned int n_values; + const uint32_t *values; - idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_FORMAT); - if (idx == SPA_IDX_INVALID) + if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_FORMAT))) return SPA_VIDEO_FORMAT_UNKNOWN; - pi = &filter->props.prop_info[idx]; - if (pi->type != SPA_PROP_TYPE_UINT32) + if (p->body.value.type != SPA_PROP_TYPE_INT) return SPA_VIDEO_FORMAT_UNKNOWN; - res = spa_props_get_value (&filter->props, idx, &val); - if (res >= 0) { + values = SPA_POD_BODY_CONST (&p->body.value); + n_values = SPA_POD_PROP_N_VALUES (p); + + if (p->body.flags & SPA_POD_PROP_FLAG_UNSET) { + if (index + 1 < n_values) + video_format = values[index + 1]; + } else { if (index == 0) - video_format = *((SpaVideoFormat *)val.value); - } else if (res == SPA_RESULT_PROPERTY_UNSET) { - - if (index < pi->n_range_values) - video_format = *((SpaVideoFormat *)pi->range_values[index].val.value); + video_format = values[0]; } } else { if (index == 0) @@ -453,9 +451,12 @@ spa_v4l2_enum_format (SpaV4l2Source *this, unsigned int index) { SpaV4l2State *state = &this->state[0]; - int res, i, pi; - V4l2Format *fmt; + int res; const FormatInfo *info; + SpaPODFrame f[2]; + SpaPODProp *prop; + SpaFormat *fmt; + SpaPODBuilder b = { state->format_buffer, sizeof (state->format_buffer), }; if (spa_v4l2_open (this) < 0) return SPA_RESULT_ERROR; @@ -506,37 +507,30 @@ next_fmtdesc: state->frmsize.pixel_format = state->fmtdesc.pixelformat; state->next_frmsize = true; } - if (!(info = fourcc_to_format_info (state->fmtdesc.pixelformat))) goto next_fmtdesc; next_frmsize: while (state->next_frmsize) { if (filter) { - const SpaPropInfo *pi; - unsigned int idx; - SpaPropValue val; - SpaResult res; + SpaPODProp *p; /* check if we have a fixed frame size */ - idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_SIZE); - if (idx == SPA_IDX_INVALID) + if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_SIZE))) goto do_frmsize; - pi = &filter->props.prop_info[idx]; - if (pi->type != SPA_PROP_TYPE_RECTANGLE) + if (p->body.value.type != SPA_PROP_TYPE_RECTANGLE) return SPA_RESULT_ENUM_END; - res = spa_props_get_value (&filter->props, idx, &val); - if (res >= 0) { - const SpaRectangle *size = val.value; + if (!(p->body.flags & SPA_POD_PROP_FLAG_UNSET)) { + const SpaRectangle *values = SPA_POD_BODY_CONST (&p->body.value); if (state->frmsize.index > 0) goto next_fmtdesc; state->frmsize.type = V4L2_FRMSIZE_TYPE_DISCRETE; - state->frmsize.discrete.width = size->width; - state->frmsize.discrete.height = size->height; + state->frmsize.discrete.width = values[0].width; + state->frmsize.discrete.height = values[0].height; goto have_size; } } @@ -549,33 +543,33 @@ do_frmsize: return SPA_RESULT_ENUM_END; } if (filter) { - const SpaPropInfo *pi; - unsigned int idx; - const SpaRectangle step = { 1, 1 }; + SpaPODProp *p; + const SpaRectangle step = { 1, 1 }, *values; + uint32_t range; + unsigned int i, n_values; /* check if we have a fixed frame size */ - idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_SIZE); - if (idx == SPA_IDX_INVALID) + if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_SIZE))) goto have_size; - /* checked above */ - pi = &filter->props.prop_info[idx]; + range = p->body.flags & SPA_POD_PROP_RANGE_MASK; + values = SPA_POD_BODY_CONST (&p->body.value); + n_values = SPA_POD_PROP_N_VALUES (p); - if (pi->range_type == SPA_PROP_RANGE_TYPE_MIN_MAX) { - if (filter_framesize (&state->frmsize, pi->range_values[0].val.value, - pi->range_values[1].val.value, + if (range == SPA_POD_PROP_RANGE_MIN_MAX && n_values > 2) { + if (filter_framesize (&state->frmsize, &values[1], + &values[2], &step)) goto have_size; - } else if (pi->range_type == SPA_PROP_RANGE_TYPE_STEP) { - if (filter_framesize (&state->frmsize, pi->range_values[0].val.value, - pi->range_values[1].val.value, - pi->range_values[2].val.value)) + } else if (range == SPA_PROP_RANGE_TYPE_STEP && n_values > 3) { + if (filter_framesize (&state->frmsize, &values[1], + &values[2], + &values[3])) goto have_size; - } else if (pi->range_type == SPA_PROP_RANGE_TYPE_ENUM) { - unsigned int i; - for (i = 0; i < pi->n_range_values; i++) { - if (filter_framesize (&state->frmsize, pi->range_values[i].val.value, - pi->range_values[i].val.value, + } else if (range == SPA_PROP_RANGE_TYPE_ENUM) { + for (i = 1; i < n_values; i++) { + if (filter_framesize (&state->frmsize, &values[i], + &values[i], &step)) goto have_size; } @@ -608,43 +602,44 @@ have_size: } } - fmt = &state->format[0]; - fmt->fmt.media_type = info->media_type; - fmt->fmt.media_subtype = info->media_subtype; - fmt->fmt.props.prop_info = fmt->infos; - fmt->fmt.props.n_prop_info = pi = 0; - fmt->fmt.props.unset_mask = 0; + fmt = SPA_MEMBER (b.data, + spa_pod_builder_push_format (&b, &f[0], + info->media_type, + info->media_subtype), + SpaFormat); if (info->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { - spa_prop_info_fill_video (&fmt->infos[pi], - SPA_PROP_ID_VIDEO_FORMAT, - offsetof (V4l2Format, format)); - fmt->format = info->format; - pi = ++fmt->fmt.props.n_prop_info; - } else { - fmt->format = info->format; + spa_pod_builder_format_prop (&b, + SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT, + info->format, + SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_READWRITE, + 0); } - spa_prop_info_fill_video (&fmt->infos[pi], - SPA_PROP_ID_VIDEO_SIZE, - offsetof (V4l2Format, size)); - fmt->size.width = state->frmsize.discrete.width; - fmt->size.height = state->frmsize.discrete.height; - pi = ++fmt->fmt.props.n_prop_info; + spa_pod_builder_format_prop (&b, + SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE, + state->frmsize.discrete.width, + state->frmsize.discrete.height, + SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_READWRITE, + 0); - spa_prop_info_fill_video (&fmt->infos[pi], - SPA_PROP_ID_VIDEO_FRAMERATE, - offsetof (V4l2Format, framerate)); - fmt->infos[pi].range_values = fmt->ranges; - fmt->infos[pi].n_range_values = 0; - i = state->frmival.index = 0; + prop = SPA_MEMBER (b.data, + spa_pod_builder_push_prop (&b, &f[1], + SPA_PROP_ID_VIDEO_FRAMERATE, + SPA_POD_PROP_RANGE_NONE | + SPA_POD_PROP_FLAG_UNSET | + SPA_POD_PROP_FLAG_READWRITE), + SpaPODProp); + spa_pod_builder_fraction (&b, 25, 1); + + state->frmival.index = 0; while (true) { if ((res = xioctl (state->fd, VIDIOC_ENUM_FRAMEINTERVALS, &state->frmival)) < 0) { if (errno == EINVAL) { state->frmsize.index++; state->next_frmsize = true; - if (i == 0) + if (state->frmival.index == 0) goto next_frmsize; break; } @@ -652,42 +647,40 @@ have_size: return SPA_RESULT_ENUM_END; } if (filter) { - SpaPropValue val; - const SpaPropInfo *pi; - unsigned int idx; - SpaResult res; - const SpaFraction step = { 1, 1 }; + SpaPODProp *p; + uint32_t range; + unsigned int i, n_values; + const SpaFraction step = { 1, 1 }, *values; - /* check against filter */ - idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_FRAMERATE); - if (idx == SPA_IDX_INVALID) + if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_FRAMERATE))) goto have_framerate; - pi = &filter->props.prop_info[idx]; - if (pi->type != SPA_PROP_TYPE_FRACTION) + if (p->body.value.type != SPA_PROP_TYPE_FRACTION) return SPA_RESULT_ENUM_END; - res = spa_props_get_value (&filter->props, idx, &val); - if (res == 0) { - if (filter_framerate (&state->frmival, val.value, - val.value, + range = p->body.flags & SPA_POD_PROP_RANGE_MASK; + values = SPA_POD_BODY_CONST (&p->body.value); + n_values = SPA_POD_PROP_N_VALUES (p); + + if (!(p->body.flags & SPA_POD_PROP_FLAG_UNSET)) { + if (filter_framerate (&state->frmival, &values[0], + &values[0], &step)) goto have_framerate; - } else if (pi->range_type == SPA_PROP_RANGE_TYPE_MIN_MAX) { - if (filter_framerate (&state->frmival, pi->range_values[0].val.value, - pi->range_values[1].val.value, + } else if (range == SPA_PROP_RANGE_TYPE_MIN_MAX && n_values > 2) { + if (filter_framerate (&state->frmival, &values[1], + &values[2], &step)) goto have_framerate; - } else if (pi->range_type == SPA_PROP_RANGE_TYPE_STEP) { - if (filter_framerate (&state->frmival, pi->range_values[0].val.value, - pi->range_values[1].val.value, - pi->range_values[2].val.value)) + } else if (range == SPA_PROP_RANGE_TYPE_STEP && n_values > 3) { + if (filter_framerate (&state->frmival, &values[1], + &values[2], + &values[3])) goto have_framerate; - } else if (pi->range_type == SPA_PROP_RANGE_TYPE_ENUM) { - unsigned int i; - for (i = 0; i < pi->n_range_values; i++) { - if (filter_framerate (&state->frmival, pi->range_values[i].val.value, - pi->range_values[i].val.value, + } else if (range == SPA_PROP_RANGE_TYPE_ENUM) { + for (i = 1; i < n_values; i++) { + if (filter_framerate (&state->frmival, &values[i], + &values[i], &step)) goto have_framerate; } @@ -697,55 +690,43 @@ have_size: } have_framerate: - fmt->ranges[i].name = NULL; + if (state->frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { - fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_ENUM; - fmt->framerates[i].num = state->frmival.discrete.denominator; - fmt->framerates[i].denom = state->frmival.discrete.numerator; - fmt->ranges[i].val.size = sizeof (SpaFraction); - fmt->ranges[i].val.value = &fmt->framerates[i]; - i++; + prop->body.flags |= SPA_PROP_RANGE_TYPE_ENUM; + spa_pod_builder_fraction (&b, + state->frmival.discrete.denominator, + state->frmival.discrete.numerator); state->frmival.index++; - if (i == 16) - break; } else if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS || state->frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { - fmt->framerates[0].num = state->frmival.stepwise.min.denominator; - fmt->framerates[0].denom = state->frmival.stepwise.min.numerator; - fmt->ranges[0].val.size = sizeof (SpaFraction); - fmt->ranges[0].val.value = &fmt->framerates[0]; - fmt->framerates[1].num = state->frmival.stepwise.max.denominator; - fmt->framerates[1].denom = state->frmival.stepwise.max.numerator; - fmt->ranges[1].val.size = sizeof (SpaFraction); - fmt->ranges[1].val.value = &fmt->framerates[1]; + spa_pod_builder_fraction (&b, + state->frmival.stepwise.min.denominator, + state->frmival.stepwise.min.numerator); + spa_pod_builder_fraction (&b, + state->frmival.stepwise.max.denominator, + state->frmival.stepwise.max.numerator); + if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) { - fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_MIN_MAX; - i = 2; + prop->body.flags |= SPA_PROP_RANGE_TYPE_MIN_MAX; } else { - fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_STEP; - fmt->framerates[2].num = state->frmival.stepwise.step.denominator; - fmt->framerates[2].denom = state->frmival.stepwise.step.numerator; - fmt->ranges[2].val.size = sizeof (SpaFraction); - fmt->ranges[2].val.value = &fmt->framerates[2]; - i = 3; + prop->body.flags |= SPA_PROP_RANGE_TYPE_STEP; + spa_pod_builder_fraction (&b, + state->frmival.stepwise.step.denominator, + state->frmival.stepwise.step.numerator); } break; } } - fmt->infos[pi].n_range_values = i; - fmt->framerate = fmt->framerates[0]; - if (i > 1) { - SPA_PROPS_INDEX_UNSET (&fmt->fmt.props, pi); - } - pi = ++fmt->fmt.props.n_prop_info; + spa_pod_builder_pop (&b, &f[1]); + spa_pod_builder_pop (&b, &f[0]); - *format = &state->format[0].fmt; + *format = fmt; return SPA_RESULT_OK; } static int -spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) +spa_v4l2_set_format (SpaV4l2Source *this, SpaVideoInfo *f, bool try_only) { SpaV4l2State *state = &this->state[0]; int cmd; @@ -758,27 +739,27 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - info = find_format_info_by_media_type (f->fmt.media_type, - f->fmt.media_subtype, - f->format, + info = find_format_info_by_media_type (f->media_type, + f->media_subtype, + f->info.raw.format, 0); if (info == NULL) { - spa_log_error (state->log, "v4l2: unknown media type %d %d %d", f->fmt.media_type, - f->fmt.media_subtype, f->format); + spa_log_error (state->log, "v4l2: unknown media type %d %d %d", f->media_type, + f->media_subtype, f->info.raw.format); return -1; } fmt.fmt.pix.pixelformat = info->fourcc; fmt.fmt.pix.field = V4L2_FIELD_ANY; - fmt.fmt.pix.width = f->size.width; - fmt.fmt.pix.height = f->size.height; - streamparm.parm.capture.timeperframe.numerator = f->framerate.denom; - streamparm.parm.capture.timeperframe.denominator = f->framerate.num; + fmt.fmt.pix.width = f->info.raw.size.width; + fmt.fmt.pix.height = f->info.raw.size.height; + streamparm.parm.capture.timeperframe.numerator = f->info.raw.framerate.denom; + streamparm.parm.capture.timeperframe.denominator = f->info.raw.framerate.num; spa_log_info (state->log, "v4l2: set %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height, - streamparm.parm.capture.timeperframe.numerator, - streamparm.parm.capture.timeperframe.denominator); + streamparm.parm.capture.timeperframe.denominator, + streamparm.parm.capture.timeperframe.numerator); reqfmt = fmt; @@ -797,8 +778,8 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) spa_log_info (state->log, "v4l2: got %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height, - streamparm.parm.capture.timeperframe.numerator, - streamparm.parm.capture.timeperframe.denominator); + streamparm.parm.capture.timeperframe.denominator, + streamparm.parm.capture.timeperframe.numerator); if (reqfmt.fmt.pix.pixelformat != fmt.fmt.pix.pixelformat || reqfmt.fmt.pix.width != fmt.fmt.pix.width || @@ -808,6 +789,11 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) if (try_only) return 0; + f->info.raw.size.width = fmt.fmt.pix.width; + f->info.raw.size.height = fmt.fmt.pix.height; + f->info.raw.framerate.num = streamparm.parm.capture.timeperframe.denominator; + f->info.raw.framerate.denom = streamparm.parm.capture.timeperframe.numerator; + state->fmt = fmt; state->info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS | SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | diff --git a/spa/plugins/videotestsrc/draw.c b/spa/plugins/videotestsrc/draw.c index 36530a197..73c8e7c70 100644 --- a/spa/plugins/videotestsrc/draw.c +++ b/spa/plugins/videotestsrc/draw.c @@ -141,11 +141,11 @@ drawing_data_init (DrawingData *dd, SpaVideoTestSrc *this, char* data) { - SpaFormatVideo *format = &this->current_format; + SpaVideoInfo *format = &this->current_format; SpaRectangle *size = &format->info.raw.size; - if (format->format.media_type != SPA_MEDIA_TYPE_VIDEO || - format->format.media_subtype != SPA_MEDIA_SUBTYPE_RAW) + if ((format->media_type != SPA_MEDIA_TYPE_VIDEO) || + (format->media_subtype != SPA_MEDIA_SUBTYPE_RAW)) return SPA_RESULT_NOT_IMPLEMENTED; switch (format->info.raw.format) { diff --git a/spa/plugins/videotestsrc/videotestsrc.c b/spa/plugins/videotestsrc/videotestsrc.c index c4ea3cf9f..dc9729349 100644 --- a/spa/plugins/videotestsrc/videotestsrc.c +++ b/spa/plugins/videotestsrc/videotestsrc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #define FRAMES_TO_TIME(this,f) ((this->current_format.info.raw.framerate.denom * (f) * SPA_NSEC_PER_SEC) / \ @@ -86,8 +87,8 @@ struct _SpaVideoTestSrc { SpaPortOutput *output; bool have_format; - SpaFormatVideo query_format; - SpaFormatVideo current_format; + SpaVideoInfo current_format; + uint8_t format_buffer[1024]; size_t bpp; VTSBuffer buffers[MAX_BUFFERS]; @@ -430,6 +431,8 @@ spa_videotestsrc_node_port_enum_formats (SpaNode *node, SpaVideoTestSrc *this; SpaResult res; SpaFormat *fmt; + uint8_t buffer[1024]; + SpaPODBuilder b = { buffer, sizeof (buffer), }; if (node == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -441,36 +444,39 @@ spa_videotestsrc_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - { - int idx; - static const uint32_t format_values[] = { - SPA_VIDEO_FORMAT_RGB, - SPA_VIDEO_FORMAT_UYVY, - }; - static const SpaPropRangeInfo format_range[] = { - { "RGB", { sizeof (uint32_t), &format_values[0] } }, - { "UYVY", { sizeof (uint32_t), &format_values[1] } }, - }; - SpaPropInfo *info; - spa_format_video_init (SPA_MEDIA_TYPE_VIDEO, - SPA_MEDIA_SUBTYPE_RAW, - &this->query_format); - - idx = spa_props_index_for_id (&this->query_format.format.props, SPA_PROP_ID_VIDEO_FORMAT); - info = (SpaPropInfo *) &this->query_format.format.props.prop_info[idx]; - - info->n_range_values = SPA_N_ELEMENTS (format_range); - info->range_values = format_range; + fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b, + SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW, + SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT, + SPA_VIDEO_FORMAT_RGB, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_ENUM, 2, + SPA_VIDEO_FORMAT_RGB, + SPA_VIDEO_FORMAT_UYVY, + SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE, + 320, 240, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_MIN_MAX, + 1, 1, + INT32_MAX, INT32_MAX, + SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, 25, 1, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_MIN_MAX, + 0, 1, + INT32_MAX, 1, + 0), SpaFormat); break; - } default: return SPA_RESULT_ENUM_END; } - if ((res = spa_format_filter (&this->query_format.format, filter, &fmt)) != SPA_RESULT_OK) + b.data = this->format_buffer; + b.size = sizeof (this->format_buffer); + b.offset = 0; + + if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK) return res; - *format = fmt; + *format = SPA_MEMBER (this->format_buffer, 0, SpaFormat); return SPA_RESULT_OK; } @@ -561,6 +567,7 @@ spa_videotestsrc_node_port_get_format (SpaNode *node, const SpaFormat **format) { SpaVideoTestSrc *this; + SpaPODBuilder b = { NULL, }; if (node == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -573,7 +580,24 @@ spa_videotestsrc_node_port_get_format (SpaNode *node, if (!this->have_format) return SPA_RESULT_NO_FORMAT; - *format = &this->current_format.format; + b.data = this->format_buffer; + b.size = sizeof (this->format_buffer); + + *format = SPA_MEMBER (b.data, spa_pod_builder_format (&b, + SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW, + SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT, + this->current_format.info.raw.format, + SPA_POD_PROP_FLAG_READWRITE, + SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE, + this->current_format.info.raw.size.width, + this->current_format.info.raw.size.height, + SPA_POD_PROP_FLAG_READWRITE, + SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, + this->current_format.info.raw.framerate.num, + this->current_format.info.raw.framerate.denom, + SPA_POD_PROP_FLAG_READWRITE, + 0), SpaFormat); + return SPA_RESULT_OK; } diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index c9e204413..6e2398ef0 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #define MAX_BUFFERS 16 @@ -79,8 +80,7 @@ struct _SpaVolume { SpaNodeEventCallback event_cb; void *user_data; - SpaFormatAudio query_format; - SpaFormatAudio current_format; + SpaAudioInfo current_format; SpaVolumePort in_ports[1]; SpaVolumePort out_ports[1]; @@ -291,6 +291,10 @@ spa_volume_node_port_enum_formats (SpaNode *node, unsigned int index) { SpaVolume *this; + SpaResult res; + SpaFormat *fmt; + uint8_t buffer[1024]; + SpaPODBuilder b = { buffer, sizeof (buffer), }; if (node == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -302,14 +306,34 @@ spa_volume_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO, - SPA_MEDIA_SUBTYPE_RAW, - &this->query_format); + fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b, + SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW, + SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT, + SPA_AUDIO_FORMAT_S16, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_ENUM, 2, + SPA_AUDIO_FORMAT_S16, + SPA_AUDIO_FORMAT_S32, + SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT, + 44100, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_MIN_MAX, + 1, INT32_MAX, + SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT, + 2, + SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE | + SPA_POD_PROP_RANGE_MIN_MAX, + 1, INT32_MAX, + 0), SpaFormat); break; default: return SPA_RESULT_ENUM_END; } - *format = &this->query_format.format; + + if ((res = spa_format_filter (fmt, filter, NULL)) != SPA_RESULT_OK) + return res; + + *format = NULL; return SPA_RESULT_OK; } @@ -405,7 +429,7 @@ spa_volume_node_port_get_format (SpaNode *node, if (!port->have_format) return SPA_RESULT_NO_FORMAT; - *format = &this->current_format.format; + *format = NULL; return SPA_RESULT_OK; } diff --git a/spa/plugins/xv/xv-sink.c b/spa/plugins/xv/xv-sink.c index 4e597e733..fa5ceac15 100644 --- a/spa/plugins/xv/xv-sink.c +++ b/spa/plugins/xv/xv-sink.c @@ -87,8 +87,8 @@ struct _SpaXvSink { SpaNodeEventCallback event_cb; void *user_data; - SpaFormatVideo format[2]; - SpaFormat *current_format; + bool have_format; + SpaVideoInfo current_format; SpaPortInfo info; SpaXvState state; @@ -304,14 +304,11 @@ spa_xv_sink_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - spa_format_video_init (SPA_MEDIA_TYPE_VIDEO, - SPA_MEDIA_SUBTYPE_RAW, - &this->format[0]); break; default: return SPA_RESULT_ENUM_END; } - *format = &this->format[0].format; + *format = NULL; return SPA_RESULT_OK; } @@ -325,8 +322,7 @@ spa_xv_sink_node_port_set_format (SpaNode *node, { SpaXvSink *this; SpaResult res; - SpaFormat *f, *tf; - size_t fs; + SpaVideoInfo info; if (node == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -337,29 +333,25 @@ spa_xv_sink_node_port_set_format (SpaNode *node, return SPA_RESULT_INVALID_PORT; if (format == NULL) { - this->current_format = NULL; + this->have_format = false; return SPA_RESULT_OK; } if (format->media_type == SPA_MEDIA_TYPE_VIDEO) { if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { - if ((res = spa_format_video_parse (format, &this->format[0]) < 0)) + if ((res = spa_format_video_parse (format, &info) < 0)) return res; - - f = &this->format[0].format; - tf = &this->format[1].format; - fs = sizeof (SpaVideoFormat); } else return SPA_RESULT_INVALID_MEDIA_TYPE; } else return SPA_RESULT_INVALID_MEDIA_TYPE; - if (spa_xv_set_format (this, f, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0) + if (spa_xv_set_format (this, &info, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0) return SPA_RESULT_INVALID_MEDIA_TYPE; if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - memcpy (tf, f, fs); - this->current_format = tf; + this->current_format = info; + this->have_format = true; } return SPA_RESULT_OK; @@ -381,10 +373,10 @@ spa_xv_sink_node_port_get_format (SpaNode *node, if (!CHECK_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - if (this->current_format == NULL) + if (!this->have_format) return SPA_RESULT_NO_FORMAT; - *format = this->current_format; + *format = NULL; return SPA_RESULT_OK; } diff --git a/spa/plugins/xv/xv-utils.c b/spa/plugins/xv/xv-utils.c index 761f73aac..e2b882d96 100644 --- a/spa/plugins/xv/xv-utils.c +++ b/spa/plugins/xv/xv-utils.c @@ -23,7 +23,7 @@ spa_xv_open (SpaXvSink *this) } static int -spa_xv_set_format (SpaXvSink *this, SpaFormat *format, bool try_only) +spa_xv_set_format (SpaXvSink *this, SpaVideoInfo *info, bool try_only) { if (spa_xv_open (this) < 0) return -1; diff --git a/spa/tests/test-props.c b/spa/tests/test-props.c index 08739b1ee..9d2c9de98 100644 --- a/spa/tests/test-props.c +++ b/spa/tests/test-props.c @@ -28,32 +28,110 @@ #include #include #include +#include #include -#include -#include -#include #include +#if 0 +/* { video/raw, + * format: (int 1) { 1 2 }, + * size: (rect (320 240)) { (1 1) (MAX MAX) }, + * framerate: (frac (25 1)) { (0 1) (MAX 1) }, + */ + +spa_build (SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW, + SPA_PROP_ID_VIDEO_FORMAT, SPA_PROP_TYPE_INT, + SPA_VIDEO_FORMAT_I420 + SPA_POD_PROP_FLAG_UNSET | + SPA_PROP_RANGE_ENUM, 2, + SPA_VIDEO_FORMAT_I420, + SPA_VIDEO_FORMAT_YUY2, + SPA_PROP_ID_VIDEO_SIZE , SPA_PROP_TYPE_RECTANGLE, + 320, 240, + SPA_POD_PROP_FLAG_UNSET | + SPA_PROP_RANGE_MIN_MAX, + 1, 1, + INT32_MAX, INT32_MAX, + SPA_PROP_ID_VIDEO_FRAMERATE, SPA_PROP_TYPE_FRACTION, 25, 1, + SPA_POD_PROP_FLAG_UNSET | + SPA_PROP_RANGE_MIN_MAX, + 0, 1, + INT32_MAX, 1, + 0); +#endif + + int main (int argc, char *argv[]) { - SpaPropBuilder b; - SpaPropBuilderInfo i[10]; - SpaPropBuilderRange r[10]; - SpaFormatVideo *f; + SpaPODBuilder b = { NULL, }; + SpaPODFrame frame[4]; + uint8_t buffer[1024]; + SpaFormat *fmt; + off_t o; - spa_prop_builder_init (&b, sizeof (SpaFormatVideo), offsetof (SpaFormatVideo, format.props)); + b.data = buffer; + b.size = 1024; - spa_format_video_builder_add (&b, &i[0], SPA_PROP_ID_VIDEO_FORMAT, offsetof (SpaFormatVideo, info.raw)); - spa_format_video_builder_add_range (&b, &r[0], SPA_VIDEO_FORMAT_I420); - spa_format_video_builder_add_range (&b, &r[1], SPA_VIDEO_FORMAT_YV12); + fmt = SPA_MEMBER (buffer, spa_pod_builder_push_format (&b, &frame[0], + SPA_MEDIA_TYPE_VIDEO, + SPA_MEDIA_SUBTYPE_RAW), SpaFormat); + spa_pod_builder_push_prop (&b, &frame[1], + SPA_PROP_ID_VIDEO_FORMAT, + SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE); + spa_pod_builder_int (&b, SPA_VIDEO_FORMAT_I420); + spa_pod_builder_int (&b, SPA_VIDEO_FORMAT_I420); + spa_pod_builder_int (&b, SPA_VIDEO_FORMAT_YUY2); + spa_pod_builder_pop (&b, &frame[1]); - b.dest = alloca (b.size); - f = spa_prop_builder_finish (&b); - f->format.media_type = SPA_MEDIA_TYPE_VIDEO; - f->format.media_subtype = SPA_MEDIA_SUBTYPE_RAW; + SpaRectangle size_min_max[] = { { 1, 1 }, { INT32_MAX, INT32_MAX } }; + spa_pod_builder_push_prop (&b, &frame[1], + SPA_PROP_ID_VIDEO_SIZE, + SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE); + spa_pod_builder_rectangle (&b, 320, 240); + spa_pod_builder_raw (&b, size_min_max, sizeof(size_min_max), false); + spa_pod_builder_pop (&b, &frame[1]); - spa_debug_format (&f->format); + SpaFraction rate_min_max[] = { { 0, 1 }, { INT32_MAX, 1 } }; + spa_pod_builder_push_prop (&b, &frame[1], + SPA_PROP_ID_VIDEO_FRAMERATE, + SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE); + spa_pod_builder_fraction (&b, 25, 1); + spa_pod_builder_raw (&b, rate_min_max, sizeof(rate_min_max), false); + spa_pod_builder_pop (&b, &frame[1]); + + spa_pod_builder_pop (&b, &frame[0]); + + spa_debug_pod (&fmt->obj.pod); + + memset (&b, 0, sizeof(b)); + b.data = buffer; + b.size = 1024; + + o = spa_pod_builder_format (&b, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW, + SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT, + SPA_VIDEO_FORMAT_I420, + SPA_POD_PROP_FLAG_UNSET | + SPA_POD_PROP_RANGE_ENUM, 2, + SPA_VIDEO_FORMAT_I420, + SPA_VIDEO_FORMAT_YUY2, + SPA_PROP_ID_VIDEO_SIZE , SPA_POD_TYPE_RECTANGLE, + 320, 240, + SPA_POD_PROP_FLAG_UNSET | + SPA_POD_PROP_RANGE_MIN_MAX, + 1, 1, + INT32_MAX, INT32_MAX, + SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, 25, 1, + SPA_POD_PROP_FLAG_UNSET | + SPA_POD_PROP_RANGE_MIN_MAX, + 0, 1, + INT32_MAX, 1, + 0); + + printf ("%zd\n", o); + fmt = SPA_MEMBER (buffer, o, SpaFormat); + printf ("%d %d\n", fmt->media_type, fmt->media_subtype); + spa_debug_pod (&fmt->obj.pod); return 0; } diff --git a/spa/tests/test-props2.c b/spa/tests/test-props2.c index 625e46a24..e12956a5d 100644 --- a/spa/tests/test-props2.c +++ b/spa/tests/test-props2.c @@ -143,10 +143,10 @@ main (int argc, char *argv[]) spa_pod_builder_int (&b, 42); spa_pod_builder_pop (&b, &frame[1]); - SpaRectangle def = { 320, 240 }, sizes[] = { { 0, 0 }, { 1024, 1024} }; + SpaRectangle sizes[] = { { 0, 0 }, { 1024, 1024} }; spa_pod_builder_push_prop (&b, &frame[1], 3, SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE); - spa_pod_builder_rectangle (&b, &def); + spa_pod_builder_rectangle (&b, 320, 240); spa_pod_builder_raw (&b, sizes, sizeof (sizes), false); spa_pod_builder_pop (&b, &frame[1]); @@ -157,9 +157,8 @@ main (int argc, char *argv[]) spa_pod_builder_float (&b, 4.0); spa_pod_builder_double (&b, 3.14); spa_pod_builder_string (&b, "test123", strlen ("test123")); - spa_pod_builder_rectangle (&b, &def); - SpaFraction f = { 25, 1 }; - spa_pod_builder_fraction (&b, &f); + spa_pod_builder_rectangle (&b, 320, 240); + spa_pod_builder_fraction (&b, 25, 1); spa_pod_builder_push_array (&b, &frame[3]); spa_pod_builder_int (&b, 4); spa_pod_builder_int (&b, 5); @@ -169,7 +168,7 @@ main (int argc, char *argv[]) spa_pod_builder_pop (&b, &frame[1]); spa_pod_builder_pop (&b, &frame[0]); - print_value (obj->size, obj->type, SPA_POD_BODY (obj), 0, 0); + spa_debug_pod (obj); SpaPODProp *p = spa_pod_object_body_find_prop (SPA_POD_BODY (obj), obj->size, 4); printf ("%d %d\n", p->body.key, p->body.flags);