diff --git a/src/screencast/pipewire_screencast.c b/src/screencast/pipewire_screencast.c index 425bc80..d00d496 100644 --- a/src/screencast/pipewire_screencast.c +++ b/src/screencast/pipewire_screencast.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "wlr_screencast.h" #include "xdpw.h" @@ -35,8 +36,10 @@ static struct spa_pod *build_buffer(struct spa_pod_builder *b, uint32_t blocks, } static struct spa_pod *build_format(struct spa_pod_builder *b, enum spa_video_format format, - uint32_t width, uint32_t height, uint32_t framerate) { - struct spa_pod_frame f[1]; + uint32_t width, uint32_t height, uint32_t framerate, + uint64_t *modifiers, int modifier_count) { + struct spa_pod_frame f[2]; + int i, c; enum spa_video_format format_without_alpha = xdpw_format_pw_strip_alpha(format); @@ -44,12 +47,31 @@ static struct spa_pod *build_format(struct spa_pod_builder *b, enum spa_video_fo spa_pod_builder_add(b, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), 0); spa_pod_builder_add(b, SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), 0); /* format */ - if (format_without_alpha == SPA_VIDEO_FORMAT_UNKNOWN) { + if (modifier_count > 0 || format_without_alpha == SPA_VIDEO_FORMAT_UNKNOWN) { + // modifiers are defined only in combinations with their format + // we should not announce the format without alpha spa_pod_builder_add(b, SPA_FORMAT_VIDEO_format, SPA_POD_Id(format), 0); } else { spa_pod_builder_add(b, SPA_FORMAT_VIDEO_format, SPA_POD_CHOICE_ENUM_Id(3, format, format, format_without_alpha), 0); } + /* modifiers */ + if (modifier_count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) { + // we only support implicit modifiers, use shortpath to skip fixation phase + spa_pod_builder_prop(b, SPA_FORMAT_VIDEO_modifier, SPA_POD_PROP_FLAG_MANDATORY); + spa_pod_builder_long(b, modifiers[0]); + } else if (modifier_count > 0) { + // build an enumeration of modifiers + spa_pod_builder_prop(b, SPA_FORMAT_VIDEO_modifier, SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE); + spa_pod_builder_push_choice(b, &f[1], SPA_CHOICE_Enum, 0); + // modifiers from the array + for (i = 0, c = 0; i < modifier_count; i++) { + spa_pod_builder_long(b, modifiers[i]); + if (c++ == 0) + spa_pod_builder_long(b, modifiers[i]); + } + spa_pod_builder_pop(b, &f[1]); + } spa_pod_builder_add(b, SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&SPA_RECTANGLE(width, height)), 0); @@ -69,7 +91,8 @@ static uint32_t build_formats(struct spa_pod_builder *b, struct xdpw_screencast_ const struct spa_pod *params[static 1]) { uint32_t param_count = 1; params[0] = build_format(b, xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[WL_SHM].format), - cast->screencopy_frame_info[WL_SHM].width, cast->screencopy_frame_info[WL_SHM].height, cast->framerate); + cast->screencopy_frame_info[WL_SHM].width, cast->screencopy_frame_info[WL_SHM].height, cast->framerate, + NULL, 0); return param_count; }