Implement control streams

spa_io_control_range -> spa_io_range
Add helpers for sequence and control pod objects
Implement control properties in audiotestsrc, update test example.
This commit is contained in:
Wim Taymans 2018-08-28 18:16:41 +02:00
parent 90c1a95eef
commit c9526dc2bb
21 changed files with 289 additions and 272 deletions

View file

@ -112,8 +112,7 @@ spa_debug_pod_value(int indent, const struct spa_type_info *info,
{
struct spa_pod_object_body *b = body;
struct spa_pod *p;
const struct spa_type_info *ti;
const struct spa_type_info *ii;
const struct spa_type_info *ti, *ii;
ti = spa_debug_type_find(info, b->type);
ii = ti ? spa_debug_type_find(ti->values, 0) : NULL;
@ -129,6 +128,30 @@ spa_debug_pod_value(int indent, const struct spa_type_info *info,
p->type, SPA_POD_BODY(p), p->size);
break;
}
case SPA_TYPE_Sequence:
{
struct spa_pod_sequence_body *b = body;
const struct spa_type_info *ti, *ii;
struct spa_pod_control *c;
ti = spa_debug_type_find(info, b->unit);
spa_debug("%*s" "Sequence: size %d, unit %s", indent, "", size,
ti ? ti->name : "unknown");
SPA_POD_SEQUENCE_BODY_FOREACH(b, size, c) {
ii = spa_debug_type_find(info, c->type);
spa_debug("%*s" "Event: offset %d, type %s", indent+2, "",
c->offset, ii ? ii->name : "unknown");
spa_debug_pod_value(indent + 2, info,
c->value.type,
SPA_POD_CONTENTS(struct spa_pod_control, c),
c->value.size);
}
break;
}
case SPA_TYPE_Prop:
{
struct spa_pod_prop_body *b = body;

View file

@ -36,10 +36,11 @@ extern "C" {
/** Different IO area types */
enum spa_io_type {
SPA_IO_Buffers,
SPA_IO_ControlRange,
SPA_IO_Range,
SPA_IO_Clock,
SPA_IO_Latency,
SPA_IO_Events,
SPA_IO_Control,
SPA_IO_Notify,
};
struct spa_io_buffers {
@ -56,7 +57,7 @@ struct spa_io_buffers {
#define SPA_IO_BUFFERS_INIT (struct spa_io_buffers) { SPA_STATUS_OK, SPA_ID_INVALID, }
/** A range, suitable for input ports that can suggest a range to output ports */
struct spa_io_control_range {
struct spa_io_range {
uint64_t offset; /**< offset in range */
uint32_t min_size; /**< minimum size of data */
uint32_t max_size; /**< maximum size of data */
@ -79,11 +80,12 @@ struct spa_io_latency {
uint64_t max; /**< max latency */
};
/** event stream */
struct spa_io_events {
/** control stream */
struct spa_io_sequence {
struct spa_pod_sequence sequence; /**< sequence of timed events */
};
#ifdef __cplusplus
} /* extern "C" */
#endif

View file

@ -28,14 +28,15 @@ extern "C" {
/** different parameter types that can be queried */
enum spa_param_type {
SPA_PARAM_List, /**< available params */
SPA_PARAM_PropInfo, /**< property information */
SPA_PARAM_Props, /**< properties */
SPA_PARAM_EnumFormat, /**< available formats */
SPA_PARAM_Format, /**< configured format */
SPA_PARAM_Buffers, /**< buffer configurations */
SPA_PARAM_Meta, /**< allowed metadata for buffers */
SPA_PARAM_IO, /**< configurable IO areas */
SPA_PARAM_START, /**< no value */
SPA_PARAM_List, /**< available params */
SPA_PARAM_PropInfo, /**< property information */
SPA_PARAM_Props, /**< properties */
SPA_PARAM_EnumFormat, /**< available formats */
SPA_PARAM_Format, /**< configured format */
SPA_PARAM_Buffers, /**< buffer configurations */
SPA_PARAM_Meta, /**< allowed metadata for buffers */
SPA_PARAM_IO, /**< configurable IO areas */
};
/** Properties for SPA_TYPE_OBJECT_ParamList */

View file

@ -34,6 +34,7 @@ extern "C" {
#define SPA_TYPE_PARAM_ID_BASE SPA_TYPE__ParamId ":"
static const struct spa_type_info spa_type_param[] = {
{ SPA_PARAM_START, "undefined", SPA_TYPE_Int, },
{ SPA_PARAM_List, SPA_TYPE_PARAM_ID_BASE "List", SPA_TYPE_Int, },
{ SPA_PARAM_PropInfo, SPA_TYPE_PARAM_ID_BASE "PropInfo", SPA_TYPE_Int, },
{ SPA_PARAM_Props, SPA_TYPE_PARAM_ID_BASE "Props", SPA_TYPE_Int, },

View file

@ -371,6 +371,25 @@ spa_pod_builder_push_prop(struct spa_pod_builder *builder, uint32_t key, uint32_
sizeof(p) - sizeof(struct spa_pod)));
}
#define SPA_POD_SEQUENCE_INIT(size,unit,...) \
(struct spa_pod_sequence){ { size, SPA_TYPE_Sequence}, {unit, 0 }, ##__VA_ARGS__ }
static inline uint32_t
spa_pod_builder_push_sequence(struct spa_pod_builder *builder, uint32_t unit)
{
const struct spa_pod_sequence p =
SPA_POD_SEQUENCE_INIT(sizeof(struct spa_pod_sequence_body), unit);
return spa_pod_builder_push(builder, &p.pod,
spa_pod_builder_raw(builder, &p, sizeof(p)));
}
static inline uint32_t
spa_pod_builder_control_header(struct spa_pod_builder *builder, uint32_t offset, uint32_t type)
{
const struct { uint32_t offset; uint32_t type; } p = { offset, type };
return spa_pod_builder_raw(builder, &p, sizeof(p));
}
static inline uint32_t spa_pod_range_from_id(char id)
{
switch (id) {
@ -400,6 +419,8 @@ static inline uint32_t spa_pod_flag_from_id(char id)
return SPA_POD_PROP_FLAG_DEPRECATED;
case 'i':
return SPA_POD_PROP_FLAG_INFO;
case 'c':
return SPA_POD_PROP_FLAG_CONTROLLABLE;
default:
return 0;
}
@ -518,6 +539,19 @@ spa_pod_builder_addv(struct spa_pod_builder *builder,
case '(':
spa_pod_builder_push_array(builder);
break;
case '{':
{
uint32_t unit = va_arg(args, uint32_t);
spa_pod_builder_push_sequence(builder, unit);
break;
}
case '.':
{
uint32_t offset = va_arg(args, uint32_t);
uint32_t type = va_arg(args, uint32_t);
spa_pod_builder_control_header(builder, offset, type);
break;
}
case ':':
{
int n_values;
@ -553,7 +587,7 @@ spa_pod_builder_addv(struct spa_pod_builder *builder,
/* don't advance format */
continue;
}
case ']': case ')': case '>':
case ']': case ')': case '>': case '}':
spa_pod_builder_pop(builder);
if (builder->state.depth > 0 &&
builder->frame[builder->state.depth-1].pod.type == SPA_TYPE_Prop)
@ -595,6 +629,12 @@ static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, const c
#define SPA_POD_PROP(key,spec,type,value,...) \
":", key, spec, value, ##__VA_ARGS__
#define SPA_POD_SEQUENCE(unit,...) \
"{", unit, ##__VA_ARGS__, "}"
#define SPA_POD_CONTROL(offset,type,...) \
".", offset, type, ##__VA_ARGS__
#define SPA_POD_PROP_MIN_MAX(min,max) 2,(min),(max)
#define SPA_POD_PROP_STEP(min,max,step) 3,(min),(max),(step)
#define SPA_POD_PROP_ENUM(n_vals,...) (n_vals),__VA_ARGS__
@ -605,6 +645,9 @@ static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, const c
#define spa_pod_builder_struct(b,...) \
spa_pod_builder_add(b, SPA_POD_STRUCT(__VA_ARGS__), NULL)
#define spa_pod_builder_sequence(b,unit,...) \
spa_pod_builder_add(b, SPA_POD_SEQUENCE(unit,__VA_ARGS__), NULL)
#ifdef __cplusplus
} /* extern "C" */
#endif

View file

@ -64,11 +64,21 @@ static inline bool spa_pod_is_inside(const void *pod, uint32_t size, const struc
return iter < SPA_MEMBER(pod, size, struct spa_pod);
}
static inline bool spa_pod_control_is_inside(const void *pod, uint32_t size, const struct spa_pod_control *iter)
{
return iter < SPA_MEMBER(pod, size, struct spa_pod_control);
}
static inline struct spa_pod *spa_pod_next(const struct spa_pod *iter)
{
return SPA_MEMBER(iter, SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), struct spa_pod);
}
static inline struct spa_pod_control *spa_pod_control_next(const struct spa_pod_control *iter)
{
return SPA_MEMBER(iter, SPA_ROUND_UP_N (SPA_POD_CONTROL_SIZE (iter), 8), struct spa_pod_control);
}
#define SPA_POD_ARRAY_BODY_FOREACH(body, _size, iter) \
for ((iter) = SPA_MEMBER((body), sizeof(struct spa_pod_array_body), __typeof__(*(iter))); \
(iter) < SPA_MEMBER((body), (_size), __typeof__(*(iter))); \
@ -90,6 +100,14 @@ static inline struct spa_pod *spa_pod_next(const struct spa_pod *iter)
#define SPA_POD_OBJECT_FOREACH(obj, iter) \
SPA_POD_OBJECT_BODY_FOREACH(&(obj)->body, SPA_POD_BODY_SIZE(obj), iter)
#define SPA_POD_SEQUENCE_BODY_FOREACH(body, size, iter) \
for ((iter) = SPA_MEMBER((body), sizeof(struct spa_pod_sequence_body), struct spa_pod_control); \
spa_pod_control_is_inside(body, size, iter); \
(iter) = spa_pod_control_next(iter))
#define SPA_POD_SEQUENCE_FOREACH(seq, iter) \
SPA_POD_SEQUENCE_BODY_FOREACH(&(seq)->body, SPA_POD_BODY_SIZE(seq), iter)
#define SPA_POD_PROP_ALTERNATIVE_FOREACH(body, _size, iter) \
for ((iter) = SPA_MEMBER((body), (body)->value.size + \
sizeof(struct spa_pod_prop_body), __typeof__(*iter)); \

View file

@ -179,6 +179,7 @@ struct spa_pod_prop_body {
#define SPA_POD_PROP_FLAG_DEPRECATED (1 << 7) /**< property is deprecated */
#define SPA_POD_PROP_FLAG_INFO (1 << 8) /**< property is informational and is not
* used when filtering */
#define SPA_POD_PROP_FLAG_CONTROLLABLE (1 << 9) /**< property can be controlled */
uint32_t flags;
struct spa_pod value;
/* array with elements of value.size follows,
@ -190,20 +191,23 @@ struct spa_pod_prop {
struct spa_pod_prop_body body;
};
/* events can be inside an event array and mark timed values */
struct spa_pod_event {
uint64_t offset;
struct spa_pod value;
#define SPA_POD_CONTROL_SIZE(ev) (sizeof(struct spa_pod_control) + (ev)->value.size)
/* controls can be inside a sequence and mark timed values */
struct spa_pod_control {
uint32_t offset; /**< media offset */
uint32_t type; /**< type of control, enum spa_control_type */
struct spa_pod value; /**< control value, depends on type */
/* value contents follow */
};
struct spa_pod_sequence_body {
uint32_t unit;
uint32_t pad;
/* array of struct spa_pod_event follows */
/* series of struct spa_pod_control follows */
};
/** a sequence of timed events */
/** a sequence of timed controls */
struct spa_pod_sequence {
struct spa_pod pod;
struct spa_pod_sequence_body body;