Format: implement intersection and fixate

This commit is contained in:
Wim Taymans 2017-02-28 15:09:34 +01:00
parent 9dd826136d
commit 7a7ede96e5
11 changed files with 205 additions and 195 deletions

View file

@ -29,7 +29,7 @@
#include "serialize.h" #include "serialize.h"
#include "log.h" #include "log.h"
#define MAX_BUFFER_SIZE 1024 #define MAX_BUFFER_SIZE 4096
#define MAX_FDS 28 #define MAX_FDS 28
typedef struct { typedef struct {

View file

@ -35,10 +35,11 @@ spa_pod_builder_push_format (SpaPODBuilder *builder,
uint32_t media_type, uint32_t media_type,
uint32_t media_subtype) uint32_t media_subtype)
{ {
const SpaFormat p = { { { sizeof (SpaPODObjectBody) + sizeof (SpaFormatBody), SPA_POD_TYPE_OBJECT }, { 0, 0 } }, const SpaFormat p = { { sizeof (SpaFormatBody), SPA_POD_TYPE_OBJECT },
{ { { sizeof (uint32_t), SPA_POD_TYPE_INT }, media_type }, { { 0, 0 },
{ { sizeof (uint32_t), SPA_POD_TYPE_INT }, media_subtype } } }; { { sizeof (uint32_t), SPA_POD_TYPE_INT }, media_type }, 0,
return spa_pod_builder_push (builder, frame, &p.obj.pod, { { sizeof (uint32_t), SPA_POD_TYPE_INT }, media_subtype }, 0 } };
return spa_pod_builder_push (builder, frame, &p.pod,
spa_pod_builder_raw (builder, &p, sizeof(p), false)); spa_pod_builder_raw (builder, &p, sizeof(p), false));
} }

View file

@ -90,8 +90,11 @@ typedef enum {
} SpaFormatProps; } SpaFormatProps;
typedef struct { typedef struct {
SpaPODObjectBody obj_body;
SpaPODInt media_type; SpaPODInt media_type;
uint32_t pad1;
SpaPODInt media_subtype; SpaPODInt media_subtype;
uint32_t pad2;
/* contents follow, series of SpaPODProp */ /* contents follow, series of SpaPODProp */
} SpaFormatBody; } SpaFormatBody;
@ -102,7 +105,7 @@ typedef struct {
* @pod: POD object with properties * @pod: POD object with properties
*/ */
struct _SpaFormat { struct _SpaFormat {
SpaPODObject obj; SpaPOD pod;
SpaFormatBody body; SpaFormatBody body;
}; };
@ -111,22 +114,23 @@ struct _SpaFormat {
(iter) < SPA_MEMBER ((body), (size), SpaPODProp); \ (iter) < SPA_MEMBER ((body), (size), SpaPODProp); \
(iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), SpaPODProp)) (iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), SpaPODProp))
#define SPA_FORMAT_FOREACH(format, iter) \
SPA_FORMAT_BODY_FOREACH(&format->body, SPA_POD_BODY_SIZE(format), iter)
static inline SpaPODProp * static inline SpaPODProp *
spa_format_find_prop (const SpaFormat *format, uint32_t key) spa_format_find_prop (const SpaFormat *format, uint32_t key)
{ {
SpaPODProp *res; return spa_pod_contents_find_prop (&format->pod, sizeof (SpaFormat), key);
SPA_FORMAT_BODY_FOREACH (&format->body, SPA_POD_BODY_SIZE (format), res) {
if (res->pod.type == SPA_POD_TYPE_PROP && res->body.key == key)
return res;
}
return NULL;
} }
static inline SpaResult static inline SpaResult
spa_format_fixate (SpaFormat *format) spa_format_fixate (SpaFormat *format)
{ {
if (format == NULL) SpaPODProp *prop;
return SPA_RESULT_INVALID_ARGUMENTS;
SPA_FORMAT_FOREACH (format, prop)
prop->body.flags &= ~SPA_POD_PROP_FLAG_UNSET;
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }

View file

@ -57,6 +57,7 @@ typedef struct {
#define SPA_POD_BODY_SIZE(pod) (((SpaPOD*)(pod))->size) #define SPA_POD_BODY_SIZE(pod) (((SpaPOD*)(pod))->size)
#define SPA_POD_SIZE(pod) (sizeof(SpaPOD) + SPA_POD_BODY_SIZE(pod)) #define SPA_POD_SIZE(pod) (sizeof(SpaPOD) + SPA_POD_BODY_SIZE(pod))
#define SPA_POD_CONTENTS_SIZE(type,pod) (SPA_POD_SIZE(pod)-sizeof(type))
#define SPA_POD_CONTENTS(type,pod) SPA_MEMBER((pod),sizeof(type),void) #define SPA_POD_CONTENTS(type,pod) SPA_MEMBER((pod),sizeof(type),void)
#define SPA_POD_CONTENTS_CONST(type,pod) SPA_MEMBER((pod),sizeof(type),const void) #define SPA_POD_CONTENTS_CONST(type,pod) SPA_MEMBER((pod),sizeof(type),const void)
@ -164,37 +165,44 @@ typedef struct {
(iter) < SPA_MEMBER (body, (size), __typeof__(*iter)); \ (iter) < SPA_MEMBER (body, (size), __typeof__(*iter)); \
(iter) = SPA_MEMBER ((iter), (body)->child.size, __typeof__(*iter))) (iter) = SPA_MEMBER ((iter), (body)->child.size, __typeof__(*iter)))
#define SPA_POD_STRUCT_BODY_FOREACH(body, size, iter) \ #define SPA_POD_FOREACH(pod, size, iter) \
for ((iter) = SPA_MEMBER ((body), 0, SpaPOD); \ for ((iter) = (pod); \
(iter) < SPA_MEMBER ((body), (size), SpaPOD); \ (iter) < SPA_MEMBER ((pod), (size), SpaPOD); \
(iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), SpaPOD)) (iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), SpaPOD))
#define SPA_POD_FOREACH(pod, iter) \ #define SPA_POD_CONTENTS_FOREACH(pod, offset, iter) \
for ((iter) = SPA_POD_CONTENTS(__typeof__(*pod), pod); \ SPA_POD_FOREACH(SPA_MEMBER ((pod), (offset), SpaPOD),SPA_POD_SIZE (pod),iter)
(iter) < SPA_MEMBER ((pod), SPA_POD_SIZE (pod), __typeof__(*iter)); \
(iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), __typeof__(*iter)))
#define SPA_POD_OBJECT_BODY_FOREACH(body, size, iter) \ #define SPA_POD_OBJECT_BODY_FOREACH(body, size, iter) \
for ((iter) = SPA_MEMBER ((body), sizeof (SpaPODObjectBody), SpaPODProp); \ for ((iter) = SPA_MEMBER ((body), sizeof (SpaPODObjectBody), SpaPODProp); \
(iter) < SPA_MEMBER ((body), (size), SpaPODProp); \ (iter) < SPA_MEMBER ((body), (size), SpaPODProp); \
(iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), SpaPODProp)) (iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), SpaPODProp))
#define SPA_POD_OBJECT_FOREACH(obj, iter) \
SPA_POD_OBJECT_BODY_FOREACH(&obj->body, SPA_POD_BODY_SIZE(obj), iter)
#define SPA_POD_PROP_ALTERNATIVE_FOREACH(body, _size, iter) \ #define SPA_POD_PROP_ALTERNATIVE_FOREACH(body, _size, iter) \
for ((iter) = SPA_MEMBER ((body), (body)->value.size + sizeof (SpaPODPropBody), __typeof__(*iter)); \ for ((iter) = SPA_MEMBER ((body), (body)->value.size + sizeof (SpaPODPropBody), __typeof__(*iter)); \
(iter) < SPA_MEMBER ((body), (_size), __typeof__(*iter)); \ (iter) < SPA_MEMBER ((body), (_size), __typeof__(*iter)); \
(iter) = SPA_MEMBER ((iter), (body)->value.size, __typeof__(*iter))) (iter) = SPA_MEMBER ((iter), (body)->value.size, __typeof__(*iter)))
static inline SpaPODProp * static inline SpaPODProp *
spa_pod_object_find_prop (const SpaPODObject *obj, uint32_t key) spa_pod_contents_find_prop (const SpaPOD *pod, off_t offset, uint32_t key)
{ {
SpaPODProp *res; SpaPOD *res;
SPA_POD_FOREACH (obj, res) { SPA_POD_CONTENTS_FOREACH (pod, offset, res) {
if (res->pod.type == SPA_POD_TYPE_PROP && res->body.key == key) if (res->type == SPA_POD_TYPE_PROP && ((SpaPODProp*)res)->body.key == key)
return res; return (SpaPODProp *)res;
} }
return NULL; return NULL;
} }
static inline SpaPODProp *
spa_pod_object_find_prop (const SpaPODObject *obj, uint32_t key)
{
return spa_pod_contents_find_prop (&obj->pod, sizeof (SpaPODObject), key);
}
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

View file

@ -88,7 +88,7 @@ spa_format_audio_parse (const SpaFormat *format,
return SPA_RESULT_INVALID_ARGUMENTS; return SPA_RESULT_INVALID_ARGUMENTS;
} }
SPA_POD_FOREACH (format, prop) { SPA_FORMAT_FOREACH (format, prop) {
if ((find = parse_info_find (pinfo, prop->body.key, prop->body.value.type))) { if ((find = parse_info_find (pinfo, prop->body.key, prop->body.value.type))) {
memcpy (SPA_MEMBER (info, find->offset, void), memcpy (SPA_MEMBER (info, find->offset, void),
SPA_POD_BODY (&prop->body.value), SPA_POD_BODY (&prop->body.value),

View file

@ -384,7 +384,7 @@ print_pod_value (uint32_t size, uint32_t type, void *body, int prefix)
{ {
SpaPOD *b = body, *p; SpaPOD *b = body, *p;
printf ("%-*sStruct: size %d\n", prefix, "", size); printf ("%-*sStruct: size %d\n", prefix, "", size);
SPA_POD_STRUCT_BODY_FOREACH (b, size, p) SPA_POD_FOREACH (b, size, p)
print_pod_value (p->size, p->type, SPA_POD_BODY (p), prefix + 2); print_pod_value (p->size, p->type, SPA_POD_BODY (p), prefix + 2);
break; break;
} }
@ -423,7 +423,6 @@ print_pod_value (uint32_t size, uint32_t type, void *body, int prefix)
} }
} }
SpaResult SpaResult
spa_debug_pod (const SpaPOD *pod) spa_debug_pod (const SpaPOD *pod)
{ {
@ -512,7 +511,7 @@ spa_debug_format (const SpaFormat *format)
fprintf (stderr, "%-6s %s/%s\n", "", media_type, media_subtype); fprintf (stderr, "%-6s %s/%s\n", "", media_type, media_subtype);
SPA_POD_FOREACH (format, prop) { SPA_FORMAT_FOREACH (format, prop) {
if ((prop->body.flags & SPA_POD_PROP_FLAG_UNSET) && if ((prop->body.flags & SPA_POD_PROP_FLAG_UNSET) &&
(prop->body.flags & SPA_POD_PROP_FLAG_OPTIONAL)) (prop->body.flags & SPA_POD_PROP_FLAG_OPTIONAL))
continue; continue;

View file

@ -1,6 +1,7 @@
spalib_sources = ['audio-raw.c', spalib_sources = ['audio-raw.c',
'debug.c', 'debug.c',
'mapper.c', 'mapper.c',
'props.c',
'video-raw.c'] 'video-raw.c']
spalib = shared_library('spa-lib', spalib = shared_library('spa-lib',

View file

@ -24,6 +24,7 @@
#include <spa/props.h> #include <spa/props.h>
#if 0
SpaResult SpaResult
spa_props_set_value (SpaProps *props, spa_props_set_value (SpaProps *props,
unsigned int index, unsigned int index,
@ -104,46 +105,31 @@ spa_props_copy_values (const SpaProps *src,
} }
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
#endif
#if 0
static int static int
compare_value (SpaPropType type, const SpaPropRangeInfo *r1, const SpaPropRangeInfo *r2) compare_value (SpaPODType type, const void *r1, const void *r2)
{ {
switch (type) { switch (type) {
case SPA_PROP_TYPE_INVALID: case SPA_POD_TYPE_INVALID:
return 0; return 0;
case SPA_PROP_TYPE_BOOL: case SPA_POD_TYPE_BOOL:
return *(bool*)r1->val.value == *(bool*)r2->val.value; return *(int32_t*)r1 == *(uint32_t*)r2;
case SPA_PROP_TYPE_INT8: case SPA_POD_TYPE_INT:
return *(int8_t*)r1->val.value - *(int8_t*)r2->val.value; printf ("%d <> %d\n", *(int32_t*)r1, *(int32_t*)r2);
case SPA_PROP_TYPE_UINT8: return *(int32_t*)r1 - *(int32_t*)r2;
return *(uint8_t*)r1->val.value - *(uint8_t*)r2->val.value; case SPA_POD_TYPE_LONG:
case SPA_PROP_TYPE_INT16: return *(int64_t*)r1 - *(int64_t*)r2;
return *(int16_t*)r1->val.value - *(int16_t*)r2->val.value; case SPA_POD_TYPE_FLOAT:
case SPA_PROP_TYPE_UINT16: return *(float*)r1 - *(float*)r2;
return *(uint16_t*)r1->val.value - *(uint16_t*)r2->val.value; case SPA_POD_TYPE_DOUBLE:
case SPA_PROP_TYPE_INT32: return *(double*)r1 - *(double*)r2;
return *(int32_t*)r1->val.value - *(int32_t*)r2->val.value; case SPA_POD_TYPE_STRING:
case SPA_PROP_TYPE_UINT32: return strcmp (r1, r2);
return *(uint32_t*)r1->val.value - *(uint32_t*)r2->val.value; case SPA_POD_TYPE_RECTANGLE:
case SPA_PROP_TYPE_INT64:
return *(int64_t*)r1->val.value - *(int64_t*)r2->val.value;
case SPA_PROP_TYPE_UINT64:
return *(uint64_t*)r1->val.value - *(uint64_t*)r2->val.value;
case SPA_PROP_TYPE_INT:
return *(int*)r1->val.value - *(int*)r2->val.value;
case SPA_PROP_TYPE_UINT:
return *(unsigned int*)r1->val.value - *(unsigned int*)r2->val.value;
case SPA_PROP_TYPE_FLOAT:
return *(float*)r1->val.value - *(float*)r2->val.value;
case SPA_PROP_TYPE_DOUBLE:
return *(double*)r1->val.value - *(double*)r2->val.value;
case SPA_PROP_TYPE_STRING:
return strcmp (r1->val.value, r2->val.value);
case SPA_PROP_TYPE_RECTANGLE:
{ {
const SpaRectangle *rec1 = r1->val.value, *rec2 = r2->val.value; const SpaRectangle *rec1 = (SpaRectangle*)r1,
*rec2 = (SpaRectangle*)r2;
if (rec1->width == rec2->width && rec1->height == rec2->height) if (rec1->width == rec2->width && rec1->height == rec2->height)
return 0; return 0;
else if (rec1->width < rec2->width || rec1->height < rec2->height) else if (rec1->width < rec2->width || rec1->height < rec2->height)
@ -151,200 +137,192 @@ compare_value (SpaPropType type, const SpaPropRangeInfo *r1, const SpaPropRangeI
else else
return 1; return 1;
} }
case SPA_PROP_TYPE_FRACTION: case SPA_POD_TYPE_FRACTION:
break; break;
case SPA_PROP_TYPE_BITMASK: default:
case SPA_PROP_TYPE_POINTER:
break; break;
} }
return 0; return 0;
} }
SpaResult SpaResult
spa_props_filter (SpaPropBuilder *b, spa_props_filter (SpaPODBuilder *b,
const SpaProps *props, const SpaPOD *props,
const SpaProps *filter) uint32_t props_size,
const SpaPOD *filter,
uint32_t filter_size)
{ {
int i, j, k; int j, k;
const SpaPOD *pr;
if (filter == NULL) SPA_POD_FOREACH (props, props_size, pr) {
return SPA_RESULT_OK; SpaPODFrame f;
SpaPODProp *p1, *p2, *np;
int nalt1, nalt2;
void *alt1, *alt2, *a1, *a2;
uint32_t rt1, rt2;
for (i = 0; i < props->n_prop_info; i++) { if (pr->type != SPA_POD_TYPE_PROP)
unsigned int idx;
const SpaPropInfo *i1, *i2;
SpaPropBuilderInfo *bi;
const SpaPropRangeInfo *ri1, *ri2;
SpaPropRangeInfo sri1, sri2;
unsigned int nri1, nri2;
SpaPropRangeType rt1, rt2;
SpaPropBuilderRange *br;
i1 = &props->prop_info[i];
idx = spa_props_index_for_id (filter, i1->id);
/* always copy the property if it turns out incomplatible with the
* filter later, we abort and return SPA_RESULT_NO_FORMAT */
bi = alloca (sizeof (SpaPropBuilderInfo));
memcpy (&bi->info, i1, sizeof (SpaPropInfo));
spa_prop_builder_add_info (b, bi);
bi->value = SPA_MEMBER (props, i1->offset, void);
if (idx == SPA_IDX_INVALID)
continue; continue;
i2 = &filter->prop_info[idx]; p1 = (SpaPODProp *) pr;
if (i1->type != i2->type) if (filter == NULL || (p2 = spa_pod_contents_find_prop (filter, 0, p1->body.key)) == NULL) {
/* no filter, copy the complete property */
spa_pod_builder_raw (b, p1, SPA_POD_SIZE (p1), true);
continue;
}
/* incompatible formats */
if (p1->body.value.type != p2->body.value.type)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
if (SPA_PROPS_INDEX_IS_UNSET (props, i)) { rt1 = p1->body.flags & SPA_POD_PROP_RANGE_MASK;
ri1 = i1->range_values; rt2 = p2->body.flags & SPA_POD_PROP_RANGE_MASK;
nri1 = i1->n_range_values;
rt1 = i1->range_type; /* else we filter. start with copying the property */
np = SPA_POD_BUILDER_DEREF (b,
spa_pod_builder_push_prop (b, &f, p1->body.key, SPA_POD_PROP_FLAG_READWRITE),
SpaPODProp);
/* size and type */
spa_pod_builder_raw (b, &p1->body.value, sizeof (p1->body.value), false);
alt1 = SPA_MEMBER (p1, sizeof (SpaPODProp), void);
nalt1 = SPA_POD_PROP_N_VALUES (p1);
alt2 = SPA_MEMBER (p2, sizeof (SpaPODProp), void);
nalt2 = SPA_POD_PROP_N_VALUES (p2);
if (p1->body.flags & SPA_POD_PROP_FLAG_UNSET) {
alt1 = SPA_MEMBER (alt1, p1->body.value.size, void);
nalt1--;
} else { } else {
sri1.name = ""; nalt1 = 1;
sri1.val.size = i1->maxsize;
sri1.val.value = SPA_MEMBER (props, i1->offset, void);
ri1 = &sri1;
nri1 = 1;
rt1 = SPA_PROP_RANGE_TYPE_NONE;
}
if (SPA_PROPS_INDEX_IS_UNSET (filter, idx)) {
ri2 = i2->range_values;
nri2 = i2->n_range_values;
rt2 = i2->range_type;
} else {
sri2.name = "";
sri2.val.size = i2->maxsize;
sri2.val.value = SPA_MEMBER (filter, i2->offset, void);
ri2 = &sri2;
nri2 = 1;
rt2 = SPA_PROP_RANGE_TYPE_NONE;
} }
if ((rt1 == SPA_PROP_RANGE_TYPE_NONE && rt2 == SPA_PROP_RANGE_TYPE_NONE) || if (p2->body.flags & SPA_POD_PROP_FLAG_UNSET) {
(rt1 == SPA_PROP_RANGE_TYPE_NONE && rt2 == SPA_PROP_RANGE_TYPE_ENUM) || alt2 = SPA_MEMBER (alt2, p2->body.value.size, void);
(rt1 == SPA_PROP_RANGE_TYPE_ENUM && rt2 == SPA_PROP_RANGE_TYPE_NONE) || nalt2--;
(rt1 == SPA_PROP_RANGE_TYPE_ENUM && rt2 == SPA_PROP_RANGE_TYPE_ENUM)) { } else {
nalt2 = 1;
}
if ((rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_NONE) ||
(rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_ENUM) ||
(rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_NONE) ||
(rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_ENUM)) {
int n_copied = 0; int n_copied = 0;
/* copy all equal values */ /* copy all equal values */
for (j = 0; j < nri1; j++) { for (j = 0, a1 = alt1; j < nalt1; j++, a1 += p1->body.value.size) {
for (k = 0; k < nri2; k++) { for (k = 0, a2 = alt2; k < nalt2; k++, a2 += p2->body.value.size) {
if (compare_value (i1->type, &ri1[j], &ri2[k]) == 0) { if (compare_value (p1->body.value.type, a1, a2) == 0) {
br = alloca (sizeof (SpaPropBuilderRange)); spa_pod_builder_raw (b, a1, p1->body.value.size, false);
memcpy (&br->info, &ri1[j], sizeof (SpaPropRangeInfo));
spa_prop_builder_add_range (b, br);
n_copied++; n_copied++;
} }
} }
} }
if (n_copied == 0) if (n_copied == 0)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
b->info->info.n_range_values = n_copied; if (n_copied == 1)
b->info->info.range_type = SPA_PROP_RANGE_TYPE_ENUM; np->body.flags |= SPA_POD_PROP_RANGE_NONE;
continue; else
np->body.flags |= SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET;
} }
if ((rt1 == SPA_PROP_RANGE_TYPE_NONE && rt2 == SPA_PROP_RANGE_TYPE_MIN_MAX) || if ((rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_MIN_MAX) ||
(rt1 == SPA_PROP_RANGE_TYPE_ENUM && rt2 == SPA_PROP_RANGE_TYPE_MIN_MAX)) { (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_MIN_MAX)) {
int n_copied = 0; int n_copied = 0;
/* copy all values inside the range */ /* copy all values inside the range */
for (j = 0; j < nri1; j++) { for (j = 0, a1 = alt1, a2 = alt2; j < nalt1; j++, a1 += p1->body.value.size) {
if (compare_value (i1->type, &ri1[j], &ri2[0]) < 0) if (compare_value (p1->body.value.type, a1, a2) < 0)
continue; continue;
if (compare_value (i1->type, &ri1[j], &ri2[1]) > 0) if (compare_value (p1->body.value.type, a1, a2 + p2->body.value.size) > 0)
continue; continue;
br = alloca (sizeof (SpaPropBuilderRange)); spa_pod_builder_raw (b, a1, p1->body.value.size, false);
memcpy (&br->info, &ri1[j], sizeof (SpaPropRangeInfo));
spa_prop_builder_add_range (b, br);
n_copied++; n_copied++;
} }
if (n_copied == 0) if (n_copied == 0)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
b->info->info.n_range_values = n_copied; if (n_copied == 1)
b->info->info.range_type = SPA_PROP_RANGE_TYPE_ENUM; np->body.flags |= SPA_POD_PROP_RANGE_NONE;
else
np->body.flags |= SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET;
} }
if (rt1 == SPA_PROP_RANGE_TYPE_NONE && rt2 == SPA_PROP_RANGE_TYPE_STEP) if (rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_STEP)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_NONE && rt2 == SPA_PROP_RANGE_TYPE_FLAGS) if (rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_FLAGS)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if ((rt1 == SPA_PROP_RANGE_TYPE_MIN_MAX && rt2 == SPA_PROP_RANGE_TYPE_NONE) || if ((rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_NONE) ||
(rt1 == SPA_PROP_RANGE_TYPE_MIN_MAX && rt2 == SPA_PROP_RANGE_TYPE_ENUM)) { (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_ENUM)) {
int n_copied = 0; int n_copied = 0;
/* copy all values inside the range */ /* copy all values inside the range */
for (k = 0; k < nri2; k++) { for (k = 0, a1 = alt2, a2 = alt2; k < nalt2; k++, a2 += p2->body.value.size) {
if (compare_value (i1->type, &ri2[k], &ri1[0]) < 0) if (compare_value (p1->body.value.type, a2, a1) < 0)
continue; continue;
if (compare_value (i1->type, &ri2[k], &ri1[1]) > 0) if (compare_value (p1->body.value.type, a2, a1 + p1->body.value.size) > 0)
continue; continue;
br = alloca (sizeof (SpaPropBuilderRange)); spa_pod_builder_raw (b, a2, p2->body.value.size, false);
memcpy (&br->info, &ri2[k], sizeof (SpaPropRangeInfo));
spa_prop_builder_add_range (b, br);
n_copied++; n_copied++;
} }
if (n_copied == 0) if (n_copied == 0)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
b->info->info.n_range_values = n_copied; if (n_copied == 1)
b->info->info.range_type = SPA_PROP_RANGE_TYPE_ENUM; np->body.flags |= SPA_POD_PROP_RANGE_NONE;
}
if (rt1 == SPA_PROP_RANGE_TYPE_MIN_MAX && rt2 == SPA_PROP_RANGE_TYPE_MIN_MAX) {
br = alloca (sizeof (SpaPropBuilderRange));
if (compare_value (i1->type, &ri1[0], &ri2[0]) < 0)
memcpy (&br->info, &ri2[0], sizeof (SpaPropRangeInfo));
else else
memcpy (&br->info, &ri1[0], sizeof (SpaPropRangeInfo)); np->body.flags |= SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET;
spa_prop_builder_add_range (b, br); }
br = alloca (sizeof (SpaPropBuilderRange)); if (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_MIN_MAX) {
if (compare_value (i1->type, &ri1[1], &ri2[1]) < 0) if (compare_value (p1->body.value.type, alt1, alt2) < 0)
memcpy (&br->info, &ri1[1], sizeof (SpaPropRangeInfo)); spa_pod_builder_raw (b, alt2, p2->body.value.size, false);
else else
memcpy (&br->info, &ri2[1], sizeof (SpaPropRangeInfo)); spa_pod_builder_raw (b, alt1, p1->body.value.size, false);
spa_prop_builder_add_range (b, br);
alt1 += p1->body.value.size;
alt2 += p2->body.value.size;
if (compare_value (p1->body.value.type, alt1, alt2) < 0)
spa_pod_builder_raw (b, alt1, p1->body.value.size, false);
else
spa_pod_builder_raw (b, alt2, p2->body.value.size, false);
} }
if (rt1 == SPA_PROP_RANGE_TYPE_MIN_MAX && rt2 == SPA_PROP_RANGE_TYPE_STEP) if (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_STEP)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_MIN_MAX && rt2 == SPA_PROP_RANGE_TYPE_FLAGS) if (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_FLAGS)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_ENUM && rt2 == SPA_PROP_RANGE_TYPE_STEP) if (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_STEP)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_ENUM && rt2 == SPA_PROP_RANGE_TYPE_FLAGS) if (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_FLAGS)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_STEP && rt2 == SPA_PROP_RANGE_TYPE_NONE) if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_NONE)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_STEP && rt2 == SPA_PROP_RANGE_TYPE_MIN_MAX) if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_MIN_MAX)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_STEP && rt2 == SPA_PROP_RANGE_TYPE_STEP) if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_STEP)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_STEP && rt2 == SPA_PROP_RANGE_TYPE_ENUM) if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_ENUM)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_STEP && rt2 == SPA_PROP_RANGE_TYPE_FLAGS) if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_FLAGS)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_FLAGS && rt2 == SPA_PROP_RANGE_TYPE_NONE) if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_NONE)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_FLAGS && rt2 == SPA_PROP_RANGE_TYPE_MIN_MAX) if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_MIN_MAX)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_FLAGS && rt2 == SPA_PROP_RANGE_TYPE_STEP) if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_STEP)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_FLAGS && rt2 == SPA_PROP_RANGE_TYPE_ENUM) if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_ENUM)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
if (rt1 == SPA_PROP_RANGE_TYPE_FLAGS && rt2 == SPA_PROP_RANGE_TYPE_FLAGS) if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_FLAGS)
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
spa_pod_builder_pop (b, &f);
} }
spa_prop_builder_finish (b);
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
#endif

View file

@ -26,6 +26,13 @@ extern "C" {
#include <spa/props.h> #include <spa/props.h>
SpaResult
spa_props_filter (SpaPODBuilder *b,
const SpaPOD *props,
uint32_t props_size,
const SpaPOD *filter,
uint32_t filter_size);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

View file

@ -25,6 +25,7 @@
#include <spa/video/raw.h> #include <spa/video/raw.h>
#include <spa/video/format.h> #include <spa/video/format.h>
#include <spa/format-builder.h> #include <spa/format-builder.h>
#include <lib/props.h>
typedef struct { typedef struct {
uint32_t key; uint32_t key;
@ -119,7 +120,7 @@ spa_format_video_parse (const SpaFormat *format,
return SPA_RESULT_INVALID_ARGUMENTS; return SPA_RESULT_INVALID_ARGUMENTS;
} }
SPA_POD_FOREACH (format, prop) { SPA_FORMAT_FOREACH (format, prop) {
if ((find = parse_info_find (pinfo, prop->body.key, prop->body.value.type))) { if ((find = parse_info_find (pinfo, prop->body.key, prop->body.value.type))) {
memcpy (SPA_MEMBER (info, find->offset, void), memcpy (SPA_MEMBER (info, find->offset, void),
SPA_POD_BODY (&prop->body.value), SPA_POD_BODY (&prop->body.value),
@ -134,6 +135,9 @@ spa_format_filter (const SpaFormat *format,
const SpaFormat *filter, const SpaFormat *filter,
SpaPODBuilder *result) SpaPODBuilder *result)
{ {
SpaPODFrame f;
SpaResult res;
if (format == NULL || result == NULL) if (format == NULL || result == NULL)
return SPA_RESULT_INVALID_ARGUMENTS; return SPA_RESULT_INVALID_ARGUMENTS;
@ -146,7 +150,15 @@ spa_format_filter (const SpaFormat *format,
filter->body.media_subtype.value != format->body.media_subtype.value) filter->body.media_subtype.value != format->body.media_subtype.value)
return SPA_RESULT_INVALID_MEDIA_TYPE; return SPA_RESULT_INVALID_MEDIA_TYPE;
spa_pod_builder_raw (result, format, SPA_POD_SIZE (format), true); spa_pod_builder_push_format (result, &f,
filter->body.media_type.value,
filter->body.media_subtype.value);
res = spa_props_filter (result,
SPA_POD_CONTENTS (SpaFormat, format),
SPA_POD_CONTENTS_SIZE (SpaFormat, format),
SPA_POD_CONTENTS (SpaFormat, filter),
SPA_POD_CONTENTS_SIZE (SpaFormat, filter));
spa_pod_builder_pop (result, &f);
return SPA_RESULT_OK; return res;
} }

View file

@ -86,10 +86,10 @@ static const struct _test_format {
} framerate_vals; } framerate_vals;
} props; } props;
} test_format = { } test_format = {
{ { { sizeof (test_format.props) + sizeof (SpaFormatBody) + sizeof (SpaPODObjectBody), SPA_POD_TYPE_OBJECT }, { { sizeof (test_format.props) + sizeof (SpaFormatBody), SPA_POD_TYPE_OBJECT },
{ 0, 0 } }, { { 0, 0 },
{ { { sizeof (uint32_t), SPA_POD_TYPE_INT }, SPA_MEDIA_TYPE_VIDEO }, { { sizeof (uint32_t), SPA_POD_TYPE_INT }, SPA_MEDIA_TYPE_VIDEO }, 0,
{ { sizeof (uint32_t), SPA_POD_TYPE_INT }, SPA_MEDIA_SUBTYPE_RAW } }, { { sizeof (uint32_t), SPA_POD_TYPE_INT }, SPA_MEDIA_SUBTYPE_RAW }, 0 },
}, { }, {
{ { sizeof (test_format.props.format_vals) + sizeof (SpaPODPropBody), { { sizeof (test_format.props.format_vals) + sizeof (SpaPODPropBody),
SPA_POD_TYPE_PROP } , SPA_POD_TYPE_PROP } ,
@ -157,7 +157,7 @@ main (int argc, char *argv[])
spa_pod_builder_pop (&b, &frame[0]); spa_pod_builder_pop (&b, &frame[0]);
spa_debug_pod (&fmt->obj.pod); spa_debug_pod (&fmt->pod);
memset (&b, 0, sizeof(b)); memset (&b, 0, sizeof(b));
b.data = buffer; b.data = buffer;
@ -184,10 +184,10 @@ main (int argc, char *argv[])
0); 0);
fmt = SPA_MEMBER (buffer, o, SpaFormat); fmt = SPA_MEMBER (buffer, o, SpaFormat);
spa_debug_pod (&fmt->obj.pod); spa_debug_pod (&fmt->pod);
spa_debug_format (fmt); spa_debug_format (fmt);
spa_debug_pod (&test_format.fmt.obj.pod); spa_debug_pod (&test_format.fmt.pod);
spa_debug_format (&test_format.fmt); spa_debug_format (&test_format.fmt);
return 0; return 0;