Rework formats

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

View file

@ -27,7 +27,7 @@ extern "C" {
#include <spa/format.h>
#include <spa/audio/raw.h>
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" */

View file

@ -0,0 +1,179 @@
/* Simple Plugin API
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __SPA_FORMAT_BUILDER_H__
#define __SPA_FORMAT_BUILDER_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include <spa/format.h>
#include <spa/pod-builder.h>
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__ */

View file

@ -26,8 +26,10 @@ extern "C" {
typedef struct _SpaFormat SpaFormat;
#include <stdarg.h>
#include <spa/defs.h>
#include <spa/props.h>
#include <spa/pod.h>
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

View file

@ -24,34 +24,30 @@
extern "C" {
#endif
typedef struct _SpaPodFrame {
struct _SpaPodFrame *parent;
off_t offset;
#include <spa/pod.h>
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

View file

@ -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) {

View file

@ -28,7 +28,7 @@ extern "C" {
#include <spa/video/raw.h>
#include <spa/video/encoded.h>
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;