diff --git a/spa/include/spa/format.h b/spa/include/spa/format.h index abb4919b1..35a705bdc 100644 --- a/spa/include/spa/format.h +++ b/spa/include/spa/format.h @@ -108,6 +108,11 @@ spa_format_fixate (SpaFormat *format) 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/video/format.h b/spa/include/spa/video/format.h index 18f78c53e..b1f97f850 100644 --- a/spa/include/spa/video/format.h +++ b/spa/include/spa/video/format.h @@ -62,9 +62,6 @@ SpaResult spa_format_video_init (SpaMediaType type, SpaResult spa_format_video_parse (const SpaFormat *format, SpaFormatVideo *dest); -SpaResult spa_format_video_filter (SpaFormatVideo *format, - const SpaFormat *filter); - struct _SpaFormatVideo { SpaFormat format; union { diff --git a/spa/lib/meson.build b/spa/lib/meson.build index 582bd4bd8..8f4a5d2dc 100644 --- a/spa/lib/meson.build +++ b/spa/lib/meson.build @@ -1,6 +1,7 @@ spalib_sources = ['audio-raw.c', 'debug.c', 'mapper.c', + 'prop-builder.c', 'props.c', 'video-raw.c'] diff --git a/spa/lib/prop-builder.c b/spa/lib/prop-builder.c new file mode 100644 index 000000000..0b5f64ecc --- /dev/null +++ b/spa/lib/prop-builder.c @@ -0,0 +1,142 @@ +/* Simple Plugin API + * Copyright (C) 2017 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. + */ + +#include +#include +#include +#include + +#include "prop-builder.h" + +void +spa_prop_builder_init (SpaPropBuilder *b, + size_t struct_size, + off_t prop_offset) +{ + memset (b, 0, sizeof (*b)); + b->size = struct_size; + b->struct_size = struct_size; + b->prop_offset = prop_offset; +} + +void +spa_prop_builder_add_info (SpaPropBuilder *b, + SpaPropBuilderInfo *i) +{ + if (b->info) + b->info->next = i; + if (b->head == NULL) + b->head = i; + b->info = i; + b->n_prop_info++; + i->info.n_range_values = 0; + i->value = NULL; + i->ranges = NULL; + i->next = NULL; + + b->size += sizeof (SpaPropInfo); + b->size += i->info.name ? strlen (i->info.name) + 1 : 0; +} + +void +spa_prop_builder_add_range (SpaPropBuilder *b, + SpaPropBuilderRange *r) +{ + if (b->range) + b->range->next = r; + b->range = r; + if (b->info->ranges == NULL) + b->info->ranges = r; + + r->next = NULL; + b->info->info.n_range_values++; + b->n_range_info++; + b->size += sizeof (SpaPropRangeInfo); + b->size += r->info.name ? strlen (r->info.name) + 1 : 0; + b->size += r->info.val.size; +} + +void * +spa_prop_builder_finish (SpaPropBuilder *b) +{ + int i, j, c, slen; + void *p; + SpaProps *tp; + SpaPropInfo *pi; + SpaPropRangeInfo *ri; + SpaPropBuilderInfo *ppi; + SpaPropBuilderRange *pri; + + if (b->dest == NULL && b->finish) + b->finish (b); + if (b->dest == NULL) + return NULL; + + tp = SPA_MEMBER (b->dest, b->prop_offset, SpaProps); + pi = SPA_MEMBER (b->dest, b->struct_size, SpaPropInfo); + ri = SPA_MEMBER (pi, sizeof(SpaPropInfo) * b->n_prop_info, SpaPropRangeInfo); + p = SPA_MEMBER (ri, sizeof(SpaPropRangeInfo) * b->n_range_info, void); + + tp->n_prop_info = b->n_prop_info; + tp->prop_info = pi; + tp->unset_mask = 0; + + ppi = b->head; + for (i = 0, c = 0; i < tp->n_prop_info; i++) { + memcpy (&pi[i], &ppi->info, sizeof (SpaPropInfo)); + pi[i].range_values = &ri[c]; + + if (pi[i].name) { + slen = strlen (pi[i].name) + 1; + memcpy (p, pi[i].name, slen); + pi[i].name = p; + p += slen; + } + + if (pi[i].n_range_values == 1) { + memcpy (SPA_MEMBER (tp, pi[i].offset, void), ppi->ranges[0].info.val.value, ppi->ranges[0].info.val.size); + ppi->value = ppi->ranges[0].info.val.value; + } else if (pi[i].n_range_values > 1) { + tp->unset_mask |= (1 << i); + } + if (ppi->value) { + memcpy (SPA_MEMBER (tp, pi[i].offset, void), ppi->value, ppi->info.maxsize); + } + + pri = ppi->ranges; + for (j = 0; j < pi[i].n_range_values; j++, c++) { + memcpy (&ri[c], &pri->info, sizeof (SpaPropRangeInfo)); + + if (ri[c].name) { + slen = strlen (ri[c].name) + 1; + memcpy (p, ri[c].name, slen); + ri[c].name = p; + p += slen; + } + if (ri[c].val.size) { + memcpy (p, ri[c].val.value, ri[c].val.size); + ri[c].val.value = p; + p += ri[c].val.size; + } + pri = pri->next; + } + ppi = ppi->next; + } + return b->dest; +} diff --git a/spa/lib/prop-builder.h b/spa/lib/prop-builder.h new file mode 100644 index 000000000..c8742bdbe --- /dev/null +++ b/spa/lib/prop-builder.h @@ -0,0 +1,80 @@ +/* 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_PROP_BUILDER_H__ +#define __SPA_PROP_BUILDER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct SpaPropBuilderRange SpaPropBuilderRange; +typedef struct SpaPropBuilderInfo SpaPropBuilderInfo; +typedef struct SpaPropBuilder SpaPropBuilder; + +struct SpaPropBuilderRange { + SpaPropBuilderRange *next; + SpaPropRangeInfo info; +}; + +struct SpaPropBuilderInfo { + SpaPropBuilderInfo *next; + SpaPropInfo info; + const void *value; + SpaPropBuilderRange *ranges; +}; + +struct SpaPropBuilder { + SpaPropBuilderInfo *head; + SpaPropBuilderInfo *info; + SpaPropBuilderRange *range; + size_t n_prop_info; + size_t n_range_info; + size_t size; + size_t struct_size; + off_t prop_offset; + void *dest; + void *userdata; + void (*finish) (SpaPropBuilder *b); +}; + + +void spa_prop_builder_init (SpaPropBuilder *b, + size_t struct_size, + off_t prop_offset); + +void spa_prop_builder_add_info (SpaPropBuilder *b, + SpaPropBuilderInfo *i); +void spa_prop_builder_add_range (SpaPropBuilder *b, + SpaPropBuilderRange *r); + +void * spa_prop_builder_finish (SpaPropBuilder *b); + +SpaResult spa_props_filter (SpaPropBuilder *b, + const SpaProps *props, + const SpaProps *filter); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* __SPA_PROP_BUILDER_H__ */ diff --git a/spa/lib/props.c b/spa/lib/props.c index 56c3e4519..fc0a2785a 100644 --- a/spa/lib/props.c +++ b/spa/lib/props.c @@ -23,6 +23,7 @@ #include #include +#include SpaResult spa_props_set_value (SpaProps *props, @@ -104,3 +105,245 @@ spa_props_copy_values (const SpaProps *src, } return SPA_RESULT_OK; } + +static int +compare_value (SpaPropType type, const SpaPropRangeInfo *r1, const SpaPropRangeInfo *r2) +{ + switch (type) { + case SPA_PROP_TYPE_INVALID: + return 0; + case SPA_PROP_TYPE_BOOL: + return *(bool*)r1->val.value == *(bool*)r2->val.value; + case SPA_PROP_TYPE_INT8: + return *(int8_t*)r1->val.value - *(int8_t*)r2->val.value; + case SPA_PROP_TYPE_UINT8: + return *(uint8_t*)r1->val.value - *(uint8_t*)r2->val.value; + case SPA_PROP_TYPE_INT16: + return *(int16_t*)r1->val.value - *(int16_t*)r2->val.value; + case SPA_PROP_TYPE_UINT16: + return *(uint16_t*)r1->val.value - *(uint16_t*)r2->val.value; + case SPA_PROP_TYPE_INT32: + return *(int32_t*)r1->val.value - *(int32_t*)r2->val.value; + case SPA_PROP_TYPE_UINT32: + return *(uint32_t*)r1->val.value - *(uint32_t*)r2->val.value; + 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; + if (rec1->width == rec2->width && rec1->height == rec2->height) + return 0; + else if (rec1->width < rec2->width || rec1->height < rec2->height) + return -1; + else + return 1; + } + case SPA_PROP_TYPE_FRACTION: + break; + case SPA_PROP_TYPE_BITMASK: + case SPA_PROP_TYPE_POINTER: + break; + } + return 0; +} + + +SpaResult +spa_props_filter (SpaPropBuilder *b, + const SpaProps *props, + const SpaProps *filter) +{ + int i, j, k; + + if (filter == NULL) + return SPA_RESULT_OK; + + for (i = 0; i < props->n_prop_info; i++) { + 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; + + i2 = &filter->prop_info[idx]; + + if (i1->type != i2->type) + return SPA_RESULT_NO_FORMAT; + + if (SPA_PROPS_INDEX_IS_UNSET (props, i)) { + ri1 = i1->range_values; + nri1 = i1->n_range_values; + rt1 = i1->range_type; + } else { + sri1.name = ""; + 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) || + (rt1 == SPA_PROP_RANGE_TYPE_NONE && rt2 == SPA_PROP_RANGE_TYPE_ENUM) || + (rt1 == SPA_PROP_RANGE_TYPE_ENUM && rt2 == SPA_PROP_RANGE_TYPE_NONE) || + (rt1 == SPA_PROP_RANGE_TYPE_ENUM && rt2 == SPA_PROP_RANGE_TYPE_ENUM)) { + int n_copied = 0; + /* copy all equal values */ + for (j = 0; j < nri1; j++) { + for (k = 0; k < nri2; k++) { + if (compare_value (i1->type, &ri1[j], &ri2[k]) == 0) { + br = alloca (sizeof (SpaPropBuilderRange)); + memcpy (&br->info, &ri1[j], sizeof (SpaPropRangeInfo)); + spa_prop_builder_add_range (b, br); + n_copied++; + } + } + } + if (n_copied == 0) + return SPA_RESULT_NO_FORMAT; + b->info->info.n_range_values = n_copied; + b->info->info.range_type = SPA_PROP_RANGE_TYPE_ENUM; + continue; + } + + if ((rt1 == SPA_PROP_RANGE_TYPE_NONE && rt2 == SPA_PROP_RANGE_TYPE_MIN_MAX) || + (rt1 == SPA_PROP_RANGE_TYPE_ENUM && rt2 == SPA_PROP_RANGE_TYPE_MIN_MAX)) { + int n_copied = 0; + /* copy all values inside the range */ + for (j = 0; j < nri1; j++) { + if (compare_value (i1->type, &ri1[j], &ri2[0]) < 0) + continue; + if (compare_value (i1->type, &ri1[j], &ri2[1]) > 0) + continue; + br = alloca (sizeof (SpaPropBuilderRange)); + memcpy (&br->info, &ri1[j], sizeof (SpaPropRangeInfo)); + spa_prop_builder_add_range (b, br); + n_copied++; + } + if (n_copied == 0) + return SPA_RESULT_NO_FORMAT; + b->info->info.n_range_values = n_copied; + b->info->info.range_type = SPA_PROP_RANGE_TYPE_ENUM; + } + + if (rt1 == SPA_PROP_RANGE_TYPE_NONE && rt2 == SPA_PROP_RANGE_TYPE_STEP) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_PROP_RANGE_TYPE_NONE && rt2 == SPA_PROP_RANGE_TYPE_FLAGS) + return SPA_RESULT_NOT_IMPLEMENTED; + + if ((rt1 == SPA_PROP_RANGE_TYPE_MIN_MAX && rt2 == SPA_PROP_RANGE_TYPE_NONE) || + (rt1 == SPA_PROP_RANGE_TYPE_MIN_MAX && rt2 == SPA_PROP_RANGE_TYPE_ENUM)) { + int n_copied = 0; + /* copy all values inside the range */ + for (k = 0; k < nri2; k++) { + if (compare_value (i1->type, &ri2[k], &ri1[0]) < 0) + continue; + if (compare_value (i1->type, &ri2[k], &ri1[1]) > 0) + continue; + br = alloca (sizeof (SpaPropBuilderRange)); + memcpy (&br->info, &ri2[k], sizeof (SpaPropRangeInfo)); + spa_prop_builder_add_range (b, br); + n_copied++; + } + if (n_copied == 0) + return SPA_RESULT_NO_FORMAT; + b->info->info.n_range_values = n_copied; + b->info->info.range_type = SPA_PROP_RANGE_TYPE_ENUM; + } + + 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 + memcpy (&br->info, &ri1[0], sizeof (SpaPropRangeInfo)); + spa_prop_builder_add_range (b, br); + + br = alloca (sizeof (SpaPropBuilderRange)); + if (compare_value (i1->type, &ri1[1], &ri2[1]) < 0) + memcpy (&br->info, &ri1[1], sizeof (SpaPropRangeInfo)); + else + memcpy (&br->info, &ri2[1], sizeof (SpaPropRangeInfo)); + spa_prop_builder_add_range (b, br); + } + if (rt1 == SPA_PROP_RANGE_TYPE_MIN_MAX && rt2 == SPA_PROP_RANGE_TYPE_STEP) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_PROP_RANGE_TYPE_MIN_MAX && rt2 == SPA_PROP_RANGE_TYPE_FLAGS) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_PROP_RANGE_TYPE_ENUM && rt2 == SPA_PROP_RANGE_TYPE_STEP) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_PROP_RANGE_TYPE_ENUM && rt2 == SPA_PROP_RANGE_TYPE_FLAGS) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_PROP_RANGE_TYPE_STEP && rt2 == SPA_PROP_RANGE_TYPE_NONE) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_PROP_RANGE_TYPE_STEP && rt2 == SPA_PROP_RANGE_TYPE_MIN_MAX) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_PROP_RANGE_TYPE_STEP && rt2 == SPA_PROP_RANGE_TYPE_STEP) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_PROP_RANGE_TYPE_STEP && rt2 == SPA_PROP_RANGE_TYPE_ENUM) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_PROP_RANGE_TYPE_STEP && rt2 == SPA_PROP_RANGE_TYPE_FLAGS) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_PROP_RANGE_TYPE_FLAGS && rt2 == SPA_PROP_RANGE_TYPE_NONE) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_PROP_RANGE_TYPE_FLAGS && rt2 == SPA_PROP_RANGE_TYPE_MIN_MAX) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_PROP_RANGE_TYPE_FLAGS && rt2 == SPA_PROP_RANGE_TYPE_STEP) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_PROP_RANGE_TYPE_FLAGS && rt2 == SPA_PROP_RANGE_TYPE_ENUM) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_PROP_RANGE_TYPE_FLAGS && rt2 == SPA_PROP_RANGE_TYPE_FLAGS) + return SPA_RESULT_NOT_IMPLEMENTED; + } + + spa_prop_builder_finish (b); + + return SPA_RESULT_OK; +} diff --git a/spa/lib/props.h b/spa/lib/props.h index 2407c3b67..fdb7c79e7 100644 --- a/spa/lib/props.h +++ b/spa/lib/props.h @@ -62,7 +62,6 @@ SpaResult spa_props_get_value (const SpaProps *props, SpaResult spa_props_copy_values (const SpaProps *src, SpaProps *dest); - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/lib/video-raw.c b/spa/lib/video-raw.c index bc7a6d50e..910c72012 100644 --- a/spa/lib/video-raw.c +++ b/spa/lib/video-raw.c @@ -25,6 +25,7 @@ #include #include +#include "video-raw.h" #include "props.h" static const uint32_t format_values[] = { @@ -95,6 +96,7 @@ static const uint32_t format_values[] = { }; 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] } }, @@ -200,6 +202,7 @@ static const uint32_t multiview_modes[] = { }; 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] } }, @@ -638,18 +641,59 @@ fallback: return res; } -SpaResult -spa_format_video_filter (SpaFormatVideo *format, - const SpaFormat *filter) +static void +prop_finish (SpaPropBuilder *b) { - SpaFormatVideo vf; + b->dest = malloc (b->size); +} + +SpaResult +spa_format_filter (const SpaFormat *format, + const SpaFormat *filter, + SpaFormat **result) +{ + SpaPropBuilder b; SpaResult res; - if (filter == NULL) + if (filter == NULL) { + *result = (SpaFormat *) format; return SPA_RESULT_OK; + } - if ((res = spa_format_video_parse (filter, &vf)) != SPA_RESULT_OK) + if (filter->media_type != format->media_type || + 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; - return SPA_RESULT_NOT_IMPLEMENTED; + *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/plugins/videotestsrc/videotestsrc.c b/spa/plugins/videotestsrc/videotestsrc.c index f9d6f6fb6..c4ea3cf9f 100644 --- a/spa/plugins/videotestsrc/videotestsrc.c +++ b/spa/plugins/videotestsrc/videotestsrc.c @@ -429,6 +429,7 @@ spa_videotestsrc_node_port_enum_formats (SpaNode *node, { SpaVideoTestSrc *this; SpaResult res; + SpaFormat *fmt; if (node == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -465,10 +466,11 @@ spa_videotestsrc_node_port_enum_formats (SpaNode *node, default: return SPA_RESULT_ENUM_END; } - if ((res = spa_format_video_filter (&this->query_format, filter)) != SPA_RESULT_OK) + + if ((res = spa_format_filter (&this->query_format.format, filter, &fmt)) != SPA_RESULT_OK) return res; - *format = &this->query_format.format; + *format = fmt; return SPA_RESULT_OK; } diff --git a/spa/tests/meson.build b/spa/tests/meson.build index faf05f43a..42b774596 100644 --- a/spa/tests/meson.build +++ b/spa/tests/meson.build @@ -9,3 +9,8 @@ # dependencies : [dl_lib, sdl_dep, pthread_lib], # link_with : spalib, # install : false) +executable('test-props', 'test-props.c', + include_directories : [spa_inc, spa_libinc ], + dependencies : [dl_lib, sdl_dep, pthread_lib], + link_with : spalib, + install : false) diff --git a/spa/tests/test-props.c b/spa/tests/test-props.c new file mode 100644 index 000000000..08739b1ee --- /dev/null +++ b/spa/tests/test-props.c @@ -0,0 +1,59 @@ +/* Spa + * Copyright (C) 2017 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. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + SpaPropBuilder b; + SpaPropBuilderInfo i[10]; + SpaPropBuilderRange r[10]; + SpaFormatVideo *f; + + spa_prop_builder_init (&b, sizeof (SpaFormatVideo), offsetof (SpaFormatVideo, format.props)); + + 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); + + 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; + + spa_debug_format (&f->format); + + return 0; +}