Skip to content

Commit 4c385fd

Browse files
committed
linux-pipewire: camera-portal: Support enumerated sizes
A node might choose to use an enumerated choice pod to report the set of supported sizes. Currently that is not supported. And what's worse, since `SPA_POD_OPT_Rectangle()` is used, if the node uses an enum choice, then `{,this_}resolution` stays uninitialized but `spa_pod_parse_object()` will not report errors because the field is considered optional. Fix this by handling `SPA_CHOICE_Enum` as well, and ignoring the unsupported choice types.
1 parent deab840 commit 4c385fd

1 file changed

Lines changed: 59 additions & 36 deletions

File tree

plugins/linux-pipewire/camera-portal.c

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,6 @@ static void camera_format_list(struct camera_device *dev, obs_property_t *prop)
353353
uint32_t media_type, media_subtype;
354354
uint32_t format = 0;
355355
const char *format_name;
356-
struct spa_rectangle resolution;
357356

358357
const struct spa_pod_prop *framerate_prop = NULL;
359358
uint32_t n_framerates = 0;
@@ -389,48 +388,58 @@ static void camera_format_list(struct camera_device *dev, obs_property_t *prop)
389388
continue;
390389
}
391390

392-
if (spa_pod_parse_object(p->param, SPA_TYPE_OBJECT_Format, format ? &format : NULL,
393-
SPA_FORMAT_VIDEO_size, SPA_POD_OPT_Rectangle(&resolution)) < 0)
391+
const struct spa_pod_prop *size_prop = spa_pod_find_prop(p->param, NULL, SPA_FORMAT_VIDEO_size);
392+
if (!size_prop)
394393
continue;
395394

396-
obs_data_set_int(data, "width", resolution.width);
397-
obs_data_set_int(data, "height", resolution.height);
395+
uint32_t n_resolutions;
396+
const struct spa_rectangle *resolutions = get_values_from_pod(&size_prop->value, SPA_TYPE_Rectangle,
397+
sizeof(*resolutions), &n_resolutions);
398+
if (!resolutions)
399+
continue;
398400

399401
framerate_prop = spa_pod_find_prop(p->param, NULL, SPA_FORMAT_VIDEO_framerate);
400402
if (framerate_prop)
401403
framerates = get_values_from_pod(&framerate_prop->value, SPA_TYPE_Fraction, sizeof(*framerates),
402404
&n_framerates);
403405

404-
dstr_printf(&str, "%ux%u", resolution.width, resolution.height);
406+
for (size_t i = 0; i < n_resolutions; i++) {
407+
const struct spa_rectangle *resolution = &resolutions[i];
405408

406-
aspect_ratio = aspect_ratio_from_spa_rectangle(resolution);
407-
if (aspect_ratio.len != 0) {
408-
dstr_catf(&str, " (%s)", aspect_ratio.array);
409-
dstr_free(&aspect_ratio);
410-
}
409+
obs_data_set_int(data, "width", resolution->width);
410+
obs_data_set_int(data, "height", resolution->height);
411411

412-
if (n_framerates > 0) {
413-
dstr_cat(&str, " - ");
412+
dstr_printf(&str, "%ux%u", resolution->width, resolution->height);
414413

415-
for (size_t i = n_framerates; i > 0; i--) {
416-
const struct spa_fraction *framerate = &framerates[i - 1];
414+
aspect_ratio = aspect_ratio_from_spa_rectangle(*resolution);
415+
if (aspect_ratio.len != 0) {
416+
dstr_catf(&str, " (%s)", aspect_ratio.array);
417+
dstr_free(&aspect_ratio);
418+
}
417419

418-
if (i != n_framerates)
419-
dstr_cat(&str, ", ");
420+
if (n_framerates > 0) {
421+
dstr_cat(&str, " - ");
420422

421-
if (framerate->denom == 1)
422-
dstr_catf(&str, "%u", framerate->num);
423-
else
424-
dstr_catf(&str, "%.2f", framerate->num / (double)framerate->denom);
425-
}
423+
for (size_t i = n_framerates; i > 0; i--) {
424+
const struct spa_fraction *framerate = &framerates[i - 1];
426425

427-
dstr_catf(&str, " FPS");
428-
}
426+
if (i != n_framerates)
427+
dstr_cat(&str, ", ");
429428

430-
dstr_catf(&str, " - %s", format_name);
429+
if (framerate->denom == 1)
430+
dstr_catf(&str, "%u", framerate->num);
431+
else
432+
dstr_catf(&str, "%.2f", framerate->num / (double)framerate->denom);
433+
}
431434

432-
obs_property_list_add_string(prop, str.array, obs_data_get_json(data));
433-
dstr_free(&str);
435+
dstr_catf(&str, " FPS");
436+
}
437+
438+
dstr_catf(&str, " - %s", format_name);
439+
440+
obs_property_list_add_string(prop, str.array, obs_data_get_json(data));
441+
dstr_free(&str);
442+
}
434443
}
435444

436445
g_clear_pointer(&data, obs_data_release);
@@ -644,8 +653,7 @@ static void framerate_list(struct camera_device *dev, uint32_t pixelformat, cons
644653
{
645654
const struct spa_fraction *framerate_values;
646655
struct obs_pw_video_format obs_pw_video_format;
647-
const struct spa_pod_prop *prop;
648-
struct spa_rectangle this_resolution;
656+
const struct spa_pod_prop *framerate_prop;
649657
uint32_t media_subtype;
650658
uint32_t media_type;
651659
uint32_t n_framerates;
@@ -672,19 +680,34 @@ static void framerate_list(struct camera_device *dev, uint32_t pixelformat, cons
672680
if (obs_pw_video_format.video_format != pixelformat)
673681
continue;
674682

675-
if (spa_pod_parse_object(p->param, SPA_TYPE_OBJECT_Format, NULL, SPA_FORMAT_VIDEO_size,
676-
SPA_POD_OPT_Rectangle(&this_resolution)) < 0)
683+
const struct spa_pod_prop *size_prop = spa_pod_find_prop(p->param, NULL, SPA_FORMAT_VIDEO_size);
684+
if (!size_prop)
685+
continue;
686+
687+
uint32_t n_resolutions;
688+
const struct spa_rectangle *resolutions = get_values_from_pod(&size_prop->value, SPA_TYPE_Rectangle,
689+
sizeof(*resolutions), &n_resolutions);
690+
if (!resolutions)
677691
continue;
678692

679-
if (this_resolution.width != resolution->width || this_resolution.height != resolution->height)
693+
bool resolution_found = false;
694+
695+
for (size_t i = 0; i < n_resolutions; i++) {
696+
resolution_found = resolutions[i].width == resolution->width &&
697+
resolutions[i].height == resolution->height;
698+
if (resolution_found)
699+
break;
700+
}
701+
702+
if (!resolution_found)
680703
continue;
681704

682-
prop = spa_pod_find_prop(p->param, NULL, SPA_FORMAT_VIDEO_framerate);
683-
if (!prop)
705+
framerate_prop = spa_pod_find_prop(p->param, NULL, SPA_FORMAT_VIDEO_framerate);
706+
if (!framerate_prop)
684707
continue;
685708

686-
framerate_values =
687-
get_values_from_pod(&prop->value, SPA_TYPE_Fraction, sizeof(*framerate_values), &n_framerates);
709+
framerate_values = get_values_from_pod(&framerate_prop->value, SPA_TYPE_Fraction,
710+
sizeof(*framerate_values), &n_framerates);
688711
if (!framerate_values)
689712
continue;
690713

0 commit comments

Comments
 (0)