mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
pod: improve parser and builder
Remove the spa_pod_iter helpers Remove builder/parser vararg recurse option, you have to manually recurse into structures when needed. This simplifies things a lot. Pass spa_pod_frames to builder and parser explicitly, we don't have to keep an internal stack anymore. The parser is now almost a mirror image of the builder. Make the parser safer when iterating over objects, add functions to check and get pod contents in a safe way. Make the builder return errno style results on errors Improve performance of object properties when they are stored and retrieved in the same order. Add many more tests for the builder and parser Add some benchmarks
This commit is contained in:
parent
878ae769ef
commit
351fb9ce29
36 changed files with 1605 additions and 973 deletions
|
|
@ -114,6 +114,7 @@ static int fill_item(struct impl *this, struct udev_device *dev,
|
|||
struct spa_pod **result, struct spa_pod_builder *builder)
|
||||
{
|
||||
const char *str, *name;
|
||||
struct spa_pod_frame f[2];
|
||||
|
||||
name = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE");
|
||||
if (!(name && *name)) {
|
||||
|
|
@ -125,7 +126,7 @@ static int fill_item(struct impl *this, struct udev_device *dev,
|
|||
if (!(name && *name))
|
||||
name = "Unknown";
|
||||
|
||||
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_MonitorItem, 0);
|
||||
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0);
|
||||
spa_pod_builder_add(builder,
|
||||
SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)),
|
||||
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE),
|
||||
|
|
@ -140,7 +141,7 @@ static int fill_item(struct impl *this, struct udev_device *dev,
|
|||
return 0;
|
||||
|
||||
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0);
|
||||
spa_pod_builder_push_struct(builder),
|
||||
spa_pod_builder_push_struct(builder, &f[1]),
|
||||
add_dict(builder,
|
||||
"udev-probed", "1",
|
||||
"device.path", udev_device_get_devnode(dev),
|
||||
|
|
@ -195,8 +196,8 @@ static int fill_item(struct impl *this, struct udev_device *dev,
|
|||
if ((str = udev_device_get_property_value(dev, "SOUND_FORM_FACTOR")) && *str) {
|
||||
add_dict(builder, "device.form_factor", str, 0);
|
||||
}
|
||||
spa_pod_builder_pop(builder);
|
||||
*result = spa_pod_builder_pop(builder);
|
||||
spa_pod_builder_pop(builder, &f[1]);
|
||||
*result = spa_pod_builder_pop(builder, &f[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <spa/node/node.h>
|
||||
#include <spa/param/audio/format.h>
|
||||
#include <spa/pod/filter.h>
|
||||
#include <spa/debug/pod.h>
|
||||
|
||||
#define NAME "alsa-sink"
|
||||
|
||||
|
|
@ -486,6 +487,8 @@ static int port_set_format(struct spa_node *node,
|
|||
info.media_subtype != SPA_MEDIA_SUBTYPE_raw)
|
||||
return -EINVAL;
|
||||
|
||||
spa_debug_pod(0, NULL, format);
|
||||
|
||||
if (spa_format_audio_raw_parse(format, &info.info.raw) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
|
|||
struct spa_pod *fmt;
|
||||
int res;
|
||||
bool opened;
|
||||
struct spa_pod_frame f[2];
|
||||
|
||||
opened = state->opened;
|
||||
if ((err = spa_alsa_open(state)) < 0)
|
||||
|
|
@ -248,7 +249,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
|
|||
snd_pcm_hw_params_alloca(¶ms);
|
||||
CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration: no configurations available");
|
||||
|
||||
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
|
||||
spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
|
||||
spa_pod_builder_add(&b,
|
||||
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
|
||||
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
|
||||
|
|
@ -262,8 +263,8 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
|
|||
|
||||
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_format, 0);
|
||||
|
||||
choice = spa_pod_builder_deref(&b,
|
||||
spa_pod_builder_push_choice(&b, SPA_CHOICE_None, 0));
|
||||
spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0);
|
||||
choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b, &f[1]);
|
||||
|
||||
for (i = 1, j = 0; i < SPA_N_ELEMENTS(format_info); i++) {
|
||||
const struct format_info *fi = &format_info[i];
|
||||
|
|
@ -284,7 +285,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
|
|||
}
|
||||
if (j > 1)
|
||||
choice->body.type = SPA_CHOICE_Enum;
|
||||
spa_pod_builder_pop(&b);
|
||||
spa_pod_builder_pop(&b, &f[1]);
|
||||
|
||||
|
||||
CHECK(snd_pcm_hw_params_get_rate_min(params, &min, &dir), "get_rate_min");
|
||||
|
|
@ -292,8 +293,8 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
|
|||
|
||||
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_rate, 0);
|
||||
|
||||
choice = spa_pod_builder_deref(&b,
|
||||
spa_pod_builder_push_choice(&b, SPA_CHOICE_None, 0));
|
||||
spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0);
|
||||
choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b, &f[1]);
|
||||
|
||||
spa_pod_builder_int(&b, SPA_CLAMP(DEFAULT_RATE, min, max));
|
||||
if (min != max) {
|
||||
|
|
@ -301,7 +302,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
|
|||
spa_pod_builder_int(&b, max);
|
||||
choice->body.type = SPA_CHOICE_Range;
|
||||
}
|
||||
spa_pod_builder_pop(&b);
|
||||
spa_pod_builder_pop(&b, &f[1]);
|
||||
|
||||
CHECK(snd_pcm_hw_params_get_channels_min(params, &min), "get_channels_min");
|
||||
CHECK(snd_pcm_hw_params_get_channels_max(params, &max), "get_channels_max");
|
||||
|
|
@ -323,13 +324,13 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
|
|||
spa_pod_builder_int(&b, map->channels);
|
||||
|
||||
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_position, 0);
|
||||
spa_pod_builder_push_array(&b);
|
||||
spa_pod_builder_push_array(&b, &f[1]);
|
||||
for (j = 0; j < map->channels; j++) {
|
||||
spa_log_debug(state->log, "position %zd %d", j, map->pos[j]);
|
||||
channel = chmap_position_to_channel(map->pos[j]);
|
||||
spa_pod_builder_id(&b, channel);
|
||||
}
|
||||
spa_pod_builder_pop(&b);
|
||||
spa_pod_builder_pop(&b, &f[1]);
|
||||
|
||||
snd_pcm_free_chmaps(maps);
|
||||
}
|
||||
|
|
@ -339,18 +340,18 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
choice = spa_pod_builder_deref(&b,
|
||||
spa_pod_builder_push_choice(&b, SPA_CHOICE_None, 0));
|
||||
spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0);
|
||||
choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b, &f[1]);
|
||||
spa_pod_builder_int(&b, SPA_CLAMP(DEFAULT_CHANNELS, min, max));
|
||||
if (min != max) {
|
||||
spa_pod_builder_int(&b, min);
|
||||
spa_pod_builder_int(&b, max);
|
||||
choice->body.type = SPA_CHOICE_Range;
|
||||
}
|
||||
spa_pod_builder_pop(&b);
|
||||
spa_pod_builder_pop(&b, &f[1]);
|
||||
}
|
||||
|
||||
fmt = spa_pod_builder_pop(&b);
|
||||
fmt = spa_pod_builder_pop(&b, &f[0]);
|
||||
|
||||
(*index)++;
|
||||
|
||||
|
|
@ -395,8 +396,10 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
|
|||
|
||||
/* set the sample format */
|
||||
format = spa_format_to_alsa(info->format);
|
||||
if (format == SND_PCM_FORMAT_UNKNOWN)
|
||||
if (format == SND_PCM_FORMAT_UNKNOWN) {
|
||||
spa_log_warn(state->log, "unknown format %u", info->format);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spa_log_info(state->log, "Stream parameters are %iHz, %s, %i channels", info->rate, snd_pcm_format_name(format),
|
||||
info->channels);
|
||||
|
|
|
|||
|
|
@ -344,12 +344,13 @@ static int port_enum_formats(struct spa_node *node,
|
|||
}
|
||||
else if (other->have_format) {
|
||||
struct spa_audio_info info;
|
||||
struct spa_pod_frame f;
|
||||
|
||||
info = other->format;
|
||||
|
||||
qsort(info.info.raw.position, info.info.raw.channels, sizeof(uint32_t), int32_cmp);
|
||||
|
||||
spa_pod_builder_push_object(builder,
|
||||
spa_pod_builder_push_object(builder, &f,
|
||||
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
|
||||
spa_pod_builder_add(builder,
|
||||
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
|
||||
|
|
@ -367,7 +368,7 @@ static int port_enum_formats(struct spa_node *node,
|
|||
spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id,
|
||||
info.info.raw.channels, info.info.raw.position);
|
||||
}
|
||||
*param = spa_pod_builder_pop(builder);
|
||||
*param = spa_pod_builder_pop(builder, &f);
|
||||
} else {
|
||||
*param = spa_pod_builder_add_object(builder,
|
||||
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
|
||||
|
|
|
|||
|
|
@ -327,13 +327,14 @@ static int port_enum_formats(struct spa_node *node,
|
|||
{
|
||||
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
|
||||
struct port *other;
|
||||
struct spa_pod_frame f;
|
||||
|
||||
other = GET_PORT(this, SPA_DIRECTION_REVERSE(direction), 0);
|
||||
|
||||
switch (*index) {
|
||||
case 0:
|
||||
if (other->have_format) {
|
||||
spa_pod_builder_push_object(builder,
|
||||
spa_pod_builder_push_object(builder, &f,
|
||||
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
|
||||
spa_pod_builder_add(builder,
|
||||
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
|
||||
|
|
@ -346,7 +347,7 @@ static int port_enum_formats(struct spa_node *node,
|
|||
spa_pod_builder_prop(builder, SPA_FORMAT_AUDIO_position, 0);
|
||||
spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id,
|
||||
other->format.info.raw.channels, other->format.info.raw.position);
|
||||
*param = spa_pod_builder_pop(builder);
|
||||
*param = spa_pod_builder_pop(builder, &f);
|
||||
} else {
|
||||
*param = spa_pod_builder_add_object(builder,
|
||||
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ static int impl_node_enum_params(struct spa_node *node,
|
|||
case SPA_PARAM_PropInfo:
|
||||
{
|
||||
struct props *p = &this->props;
|
||||
struct spa_pod_frame f[2];
|
||||
|
||||
switch (*index) {
|
||||
case 0:
|
||||
|
|
@ -172,20 +173,20 @@ static int impl_node_enum_params(struct spa_node *node,
|
|||
SPA_PROP_INFO_type, SPA_POD_Bool(p->live));
|
||||
break;
|
||||
case 1:
|
||||
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_PropInfo, id);
|
||||
spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
|
||||
spa_pod_builder_add(&b,
|
||||
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_waveType),
|
||||
SPA_PROP_INFO_name, SPA_POD_String("Select the waveform"),
|
||||
SPA_PROP_INFO_type, SPA_POD_Int(p->wave),
|
||||
0);
|
||||
spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0);
|
||||
spa_pod_builder_push_struct(&b);
|
||||
spa_pod_builder_push_struct(&b, &f[1]);
|
||||
spa_pod_builder_int(&b, WAVE_SINE);
|
||||
spa_pod_builder_string(&b, "Sine wave");
|
||||
spa_pod_builder_int(&b, WAVE_SQUARE);
|
||||
spa_pod_builder_string(&b, "Square wave");
|
||||
spa_pod_builder_pop(&b);
|
||||
param = spa_pod_builder_pop(&b);
|
||||
spa_pod_builder_pop(&b, &f[1]);
|
||||
param = spa_pod_builder_pop(&b, &f[0]);
|
||||
break;
|
||||
case 2:
|
||||
param = spa_pod_builder_add_object(&b,
|
||||
|
|
|
|||
|
|
@ -89,8 +89,9 @@ static void fill_item(struct spa_bt_monitor *this, struct spa_bt_device *device,
|
|||
struct spa_pod **result, struct spa_pod_builder *builder)
|
||||
{
|
||||
char dev[16];
|
||||
struct spa_pod_frame f[2];
|
||||
|
||||
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_MonitorItem, 0);
|
||||
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0);
|
||||
spa_pod_builder_add(builder,
|
||||
SPA_MONITOR_ITEM_id, SPA_POD_String(device->path),
|
||||
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE),
|
||||
|
|
@ -103,7 +104,7 @@ static void fill_item(struct spa_bt_monitor *this, struct spa_bt_device *device,
|
|||
0);
|
||||
|
||||
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0);
|
||||
spa_pod_builder_push_struct(builder);
|
||||
spa_pod_builder_push_struct(builder, &f[1]);
|
||||
snprintf(dev, sizeof(dev), "%p", device);
|
||||
|
||||
add_dict(builder, "device.api", "bluez5");
|
||||
|
|
@ -113,8 +114,8 @@ static void fill_item(struct spa_bt_monitor *this, struct spa_bt_device *device,
|
|||
add_dict(builder, "device.bluez5.address", device->address);
|
||||
add_dict(builder, "bluez5.device", dev);
|
||||
|
||||
spa_pod_builder_pop(builder);
|
||||
*result = spa_pod_builder_pop(builder);
|
||||
spa_pod_builder_pop(builder, &f[1]);
|
||||
*result = spa_pod_builder_pop(builder, &f[0]);
|
||||
}
|
||||
|
||||
static uint8_t a2dp_default_bitpool(struct spa_bt_monitor *monitor, uint8_t freq, uint8_t mode) {
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ static void fill_item(struct impl *this, struct udev_device *dev,
|
|||
struct spa_pod **result, struct spa_pod_builder *builder)
|
||||
{
|
||||
const char *str, *name;
|
||||
struct spa_pod_frame f[2];
|
||||
|
||||
name = udev_device_get_property_value(dev, "ID_V4L_PRODUCT");
|
||||
if (!(name && *name)) {
|
||||
|
|
@ -98,7 +99,7 @@ static void fill_item(struct impl *this, struct udev_device *dev,
|
|||
if (!(name && *name))
|
||||
name = "Unknown";
|
||||
|
||||
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_MonitorItem, 0);
|
||||
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0);
|
||||
spa_pod_builder_add(builder,
|
||||
SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)),
|
||||
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE),
|
||||
|
|
@ -110,7 +111,7 @@ static void fill_item(struct impl *this, struct udev_device *dev,
|
|||
0);
|
||||
|
||||
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0);
|
||||
spa_pod_builder_push_struct(builder);
|
||||
spa_pod_builder_push_struct(builder, &f[1]);
|
||||
add_dict(builder, "udev-probed", "1");
|
||||
add_dict(builder, "device.path", udev_device_get_devnode(dev));
|
||||
|
||||
|
|
@ -159,8 +160,8 @@ static void fill_item(struct impl *this, struct udev_device *dev,
|
|||
add_dict(builder, "device.capabilities", str);
|
||||
}
|
||||
|
||||
spa_pod_builder_pop(builder);
|
||||
*result = spa_pod_builder_pop(builder);
|
||||
spa_pod_builder_pop(builder, &f[1]);
|
||||
*result = spa_pod_builder_pop(builder, &f[0]);
|
||||
}
|
||||
|
||||
static int emit_device(struct impl *this, uint32_t id, struct udev_device *dev)
|
||||
|
|
|
|||
|
|
@ -430,13 +430,14 @@ static int port_get_format(struct spa_node *node,
|
|||
{
|
||||
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
|
||||
struct port *port = GET_PORT(this, direction, port_id);
|
||||
struct spa_pod_frame f;
|
||||
|
||||
if (!port->have_format)
|
||||
return -EIO;
|
||||
if (*index > 0)
|
||||
return 0;
|
||||
|
||||
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_Format);
|
||||
spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_Format);
|
||||
spa_pod_builder_add(builder,
|
||||
SPA_FORMAT_mediaType, SPA_POD_Id(port->current_format.media_type),
|
||||
SPA_FORMAT_mediaSubtype, SPA_POD_Id(port->current_format.media_subtype),
|
||||
|
|
@ -467,7 +468,7 @@ static int port_get_format(struct spa_node *node,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
*param = spa_pod_builder_pop(builder);
|
||||
*param = spa_pod_builder_pop(builder, &f);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -402,12 +402,12 @@ enum_filter_format(uint32_t media_type, int32_t media_subtype,
|
|||
case SPA_MEDIA_TYPE_video:
|
||||
case SPA_MEDIA_TYPE_image:
|
||||
if (media_subtype == SPA_MEDIA_SUBTYPE_raw) {
|
||||
struct spa_pod_prop *p;
|
||||
const struct spa_pod_prop *p;
|
||||
const struct spa_pod *val;
|
||||
uint32_t n_values, choice;
|
||||
const uint32_t *values;
|
||||
|
||||
if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_format)))
|
||||
if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_format)))
|
||||
return SPA_VIDEO_FORMAT_UNKNOWN;
|
||||
|
||||
val = spa_pod_get_values(&p->value, &n_values, &choice);
|
||||
|
|
@ -532,6 +532,7 @@ spa_v4l2_enum_format(struct impl *this,
|
|||
struct spa_pod_choice *choice;
|
||||
uint32_t filter_media_type, filter_media_subtype, video_format;
|
||||
struct spa_v4l2_device *dev = &port->dev;
|
||||
struct spa_pod_frame f[2];
|
||||
|
||||
if ((res = spa_v4l2_open(dev, this->props.device)) < 0)
|
||||
return res;
|
||||
|
|
@ -592,12 +593,12 @@ spa_v4l2_enum_format(struct impl *this,
|
|||
next_frmsize:
|
||||
while (port->next_frmsize) {
|
||||
if (filter) {
|
||||
struct spa_pod_prop *p;
|
||||
const struct spa_pod_prop *p;
|
||||
struct spa_pod *val;
|
||||
uint32_t n_vals, choice;
|
||||
|
||||
/* check if we have a fixed frame size */
|
||||
if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_size)))
|
||||
if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_size)))
|
||||
goto do_frmsize;
|
||||
|
||||
val = spa_pod_get_values(&p->value, &n_vals, &choice);
|
||||
|
|
@ -626,13 +627,13 @@ spa_v4l2_enum_format(struct impl *this,
|
|||
goto exit;
|
||||
}
|
||||
if (filter) {
|
||||
struct spa_pod_prop *p;
|
||||
const struct spa_pod_prop *p;
|
||||
struct spa_pod *val;
|
||||
const struct spa_rectangle step = { 1, 1 }, *values;
|
||||
uint32_t choice, i, n_values;
|
||||
|
||||
/* check if we have a fixed frame size */
|
||||
if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_size)))
|
||||
if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_size)))
|
||||
goto have_size;
|
||||
|
||||
val = spa_pod_get_values(&p->value, &n_values, &choice);
|
||||
|
|
@ -680,7 +681,7 @@ spa_v4l2_enum_format(struct impl *this,
|
|||
}
|
||||
}
|
||||
|
||||
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
|
||||
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
|
||||
spa_pod_builder_add(builder,
|
||||
SPA_FORMAT_mediaType, SPA_POD_Id(info->media_type),
|
||||
SPA_FORMAT_mediaSubtype, SPA_POD_Id(info->media_subtype),
|
||||
|
|
@ -697,8 +698,8 @@ spa_v4l2_enum_format(struct impl *this,
|
|||
|
||||
n_fractions = 0;
|
||||
|
||||
choice = spa_pod_builder_deref(builder,
|
||||
spa_pod_builder_push_choice(builder, SPA_CHOICE_None, 0));
|
||||
spa_pod_builder_push_choice(builder, &f[1], SPA_CHOICE_None, 0);
|
||||
choice = (struct spa_pod_choice*)spa_pod_builder_frame(builder, &f[1]);
|
||||
port->frmival.index = 0;
|
||||
|
||||
while (true) {
|
||||
|
|
@ -715,12 +716,12 @@ spa_v4l2_enum_format(struct impl *this,
|
|||
goto exit;
|
||||
}
|
||||
if (filter) {
|
||||
struct spa_pod_prop *p;
|
||||
const struct spa_pod_prop *p;
|
||||
struct spa_pod *val;
|
||||
uint32_t i, n_values, choice;
|
||||
const struct spa_fraction step = { 1, 1 }, *values;
|
||||
|
||||
if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_framerate)))
|
||||
if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_framerate)))
|
||||
goto have_framerate;
|
||||
|
||||
val = spa_pod_get_values(&p->value, &n_values, &choice);
|
||||
|
|
@ -800,8 +801,8 @@ spa_v4l2_enum_format(struct impl *this,
|
|||
if (n_fractions <= 1)
|
||||
choice->body.type = SPA_CHOICE_None;
|
||||
|
||||
spa_pod_builder_pop(builder);
|
||||
*result = spa_pod_builder_pop(builder);
|
||||
spa_pod_builder_pop(builder, &f[1]);
|
||||
*result = spa_pod_builder_pop(builder, &f[0]);
|
||||
|
||||
(*index)++;
|
||||
|
||||
|
|
@ -1009,6 +1010,7 @@ spa_v4l2_enum_controls(struct impl *this,
|
|||
uint8_t buffer[1024];
|
||||
int res;
|
||||
const unsigned next_fl = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
|
||||
struct spa_pod_frame f[2];
|
||||
|
||||
if ((res = spa_v4l2_open(dev, this->props.device)) < 0)
|
||||
return res;
|
||||
|
|
@ -1091,7 +1093,7 @@ spa_v4l2_enum_controls(struct impl *this,
|
|||
{
|
||||
struct v4l2_querymenu querymenu;
|
||||
|
||||
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo);
|
||||
spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo);
|
||||
spa_pod_builder_add(&b,
|
||||
SPA_PROP_INFO_id, SPA_POD_Id(prop_id),
|
||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_ENUM_Int(1, queryctrl.default_value),
|
||||
|
|
@ -1102,7 +1104,7 @@ spa_v4l2_enum_controls(struct impl *this,
|
|||
querymenu.id = queryctrl.id;
|
||||
|
||||
spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0);
|
||||
spa_pod_builder_push_struct(&b);
|
||||
spa_pod_builder_push_struct(&b, &f[1]);
|
||||
for (querymenu.index = queryctrl.minimum;
|
||||
querymenu.index <= queryctrl.maximum;
|
||||
querymenu.index++) {
|
||||
|
|
@ -1111,8 +1113,8 @@ spa_v4l2_enum_controls(struct impl *this,
|
|||
spa_pod_builder_string(&b, (const char *)querymenu.name);
|
||||
}
|
||||
}
|
||||
spa_pod_builder_pop(&b);
|
||||
param = spa_pod_builder_pop(&b);
|
||||
spa_pod_builder_pop(&b, &f[1]);
|
||||
param = spa_pod_builder_pop(&b, &f[0]);
|
||||
break;
|
||||
}
|
||||
case V4L2_CTRL_TYPE_INTEGER_MENU:
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ static int impl_node_enum_params(struct spa_node *node,
|
|||
case SPA_PARAM_PropInfo:
|
||||
{
|
||||
struct props *p = &this->props;
|
||||
struct spa_pod_frame f[2];
|
||||
|
||||
switch (*index) {
|
||||
case 0:
|
||||
|
|
@ -156,20 +157,20 @@ static int impl_node_enum_params(struct spa_node *node,
|
|||
SPA_PROP_INFO_type, SPA_POD_Bool(p->live));
|
||||
break;
|
||||
case 1:
|
||||
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_PropInfo, id);
|
||||
spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
|
||||
spa_pod_builder_add(&b,
|
||||
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_patternType),
|
||||
SPA_PROP_INFO_name, SPA_POD_String("The pattern"),
|
||||
SPA_PROP_INFO_type, SPA_POD_Int(p->pattern),
|
||||
0);
|
||||
spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0),
|
||||
spa_pod_builder_push_struct(&b);
|
||||
spa_pod_builder_push_struct(&b, &f[1]);
|
||||
spa_pod_builder_int(&b, PATTERN_SMPTE_SNOW);
|
||||
spa_pod_builder_string(&b, "SMPTE snow");
|
||||
spa_pod_builder_int(&b, PATTERN_SNOW);
|
||||
spa_pod_builder_string(&b, "Snow");
|
||||
spa_pod_builder_pop(&b);
|
||||
param = spa_pod_builder_pop(&b);
|
||||
spa_pod_builder_pop(&b, &f[1]);
|
||||
param = spa_pod_builder_pop(&b, &f[0]);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue