diff --git a/src/screencast/pipewire_screencast.c b/src/screencast/pipewire_screencast.c index 28b7716..59e6fe4 100644 --- a/src/screencast/pipewire_screencast.c +++ b/src/screencast/pipewire_screencast.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -139,7 +140,7 @@ static bool build_modifierlist(struct xdpw_screencast_instance *cast, return ret; } -static uint32_t build_formats(struct spa_pod_builder *b, struct xdpw_screencast_instance *cast, +static uint32_t build_formats(struct spa_pod_builder *b[static 2], struct xdpw_screencast_instance *cast, const struct spa_pod *params[static 2]) { uint32_t param_count; uint32_t modifier_count; @@ -148,17 +149,20 @@ static uint32_t build_formats(struct spa_pod_builder *b, struct xdpw_screencast_ if (!cast->avoid_dmabufs && build_modifierlist(cast, cast->screencopy_frame_info[DMABUF].format, &modifiers, &modifier_count) && modifier_count > 0) { param_count = 2; - params[0] = build_format(b, xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[DMABUF].format), + params[0] = build_format(b[0], xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[DMABUF].format), cast->screencopy_frame_info[DMABUF].width, cast->screencopy_frame_info[DMABUF].height, cast->framerate, modifiers, modifier_count); - params[1] = build_format(b, xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[WL_SHM].format), + assert(params[0] != NULL); + params[1] = build_format(b[1], 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, NULL, 0); + assert(params[1] != NULL); } else { param_count = 1; - params[0] = build_format(b, xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[WL_SHM].format), + params[0] = build_format(b[0], 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, NULL, 0); + assert(params[0] != NULL); } free(modifiers); return param_count; @@ -196,9 +200,8 @@ static void pwr_handle_stream_param_changed(void *data, uint32_t id, logprint(TRACE, "pipewire: stream parameters changed"); struct xdpw_screencast_instance *cast = data; struct pw_stream *stream = cast->stream; - uint8_t params_buffer[1024]; - struct spa_pod_builder b = - SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer)); + uint8_t params_buffer[3][1024]; + struct spa_pod_dynamic_builder b[3]; const struct spa_pod *params[3]; uint32_t blocks; uint32_t data_type; @@ -207,6 +210,10 @@ static void pwr_handle_stream_param_changed(void *data, uint32_t id, return; } + spa_pod_dynamic_builder_init(&b[0], params_buffer[0], sizeof(params_buffer[0]), 2048); + spa_pod_dynamic_builder_init(&b[1], params_buffer[1], sizeof(params_buffer[1]), 2048); + spa_pod_dynamic_builder_init(&b[2], params_buffer[2], sizeof(params_buffer[2]), 2048); + spa_format_video_raw_parse(param, &cast->pwr_format); cast->framerate = (uint32_t)(cast->pwr_format.max_framerate.num / cast->pwr_format.max_framerate.denom); @@ -224,6 +231,7 @@ static void pwr_handle_stream_param_changed(void *data, uint32_t id, uint32_t flags = GBM_BO_USE_RENDERING; uint64_t modifier; uint32_t n_params; + struct spa_pod_builder *builder[2] = {&b[0].b, &b[1].b}; struct gbm_bo *bo = gbm_bo_create_with_modifiers2(cast->ctx->gbm, cast->screencopy_frame_info[cast->buffer_type].width, cast->screencopy_frame_info[cast->buffer_type].height, @@ -260,18 +268,24 @@ static void pwr_handle_stream_param_changed(void *data, uint32_t id, logprint(WARN, "pipewire: unable to allocate a dmabuf. Falling back to shm"); cast->avoid_dmabufs = true; - n_params = build_formats(&b, cast, ¶ms[0]); + n_params = build_formats(builder, cast, ¶ms[0]); pw_stream_update_params(stream, params, n_params); + spa_pod_dynamic_builder_clean(&b[0]); + spa_pod_dynamic_builder_clean(&b[1]); + spa_pod_dynamic_builder_clean(&b[2]); return; fixate_format: - params[0] = fixate_format(&b, xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[cast->buffer_type].format), + params[0] = fixate_format(&b[2].b, xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[cast->buffer_type].format), cast->screencopy_frame_info[cast->buffer_type].width, cast->screencopy_frame_info[cast->buffer_type].height, cast->framerate, &modifier); - n_params = build_formats(&b, cast, ¶ms[1]); + n_params = build_formats(builder, cast, ¶ms[1]); n_params++; pw_stream_update_params(stream, params, n_params); + spa_pod_dynamic_builder_clean(&b[0]); + spa_pod_dynamic_builder_clean(&b[1]); + spa_pod_dynamic_builder_clean(&b[2]); return; } @@ -294,15 +308,17 @@ fixate_format: logprint(DEBUG, "pipewire: size: (%u, %u)", cast->pwr_format.size.width, cast->pwr_format.size.height); logprint(DEBUG, "pipewire: max_framerate: (%u / %u)", cast->pwr_format.max_framerate.num, cast->pwr_format.max_framerate.denom); - params[0] = build_buffer(&b, blocks, cast->screencopy_frame_info[cast->buffer_type].size, + params[0] = build_buffer(&b[0].b, blocks, cast->screencopy_frame_info[cast->buffer_type].size, cast->screencopy_frame_info[cast->buffer_type].stride, data_type); - params[1] = spa_pod_builder_add_object(&b, + params[1] = spa_pod_builder_add_object(&b[1].b, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header), SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header))); pw_stream_update_params(stream, params, 2); + spa_pod_dynamic_builder_clean(&b[0]); + spa_pod_dynamic_builder_clean(&b[1]); } static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) { @@ -456,14 +472,18 @@ done: void pwr_update_stream_param(struct xdpw_screencast_instance *cast) { logprint(TRACE, "pipewire: stream update parameters"); struct pw_stream *stream = cast->stream; - uint8_t params_buffer[1024]; - struct spa_pod_builder b = - SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer)); + uint8_t params_buffer[2][1024]; + struct spa_pod_dynamic_builder b[2]; + spa_pod_dynamic_builder_init(&b[0], params_buffer[0], sizeof(params_buffer[0]), 2048); + spa_pod_dynamic_builder_init(&b[1], params_buffer[1], sizeof(params_buffer[1]), 2048); const struct spa_pod *params[2]; - uint32_t n_params = build_formats(&b, cast, params); + struct spa_pod_builder *builder[2] = {&b[0].b, &b[1].b}; + uint32_t n_params = build_formats(builder, cast, params); pw_stream_update_params(stream, params, n_params); + spa_pod_dynamic_builder_clean(&b[0]); + spa_pod_dynamic_builder_clean(&b[1]); } void xdpw_pwr_stream_create(struct xdpw_screencast_instance *cast) { @@ -472,8 +492,10 @@ void xdpw_pwr_stream_create(struct xdpw_screencast_instance *cast) { pw_loop_enter(state->pw_loop); - uint8_t buffer[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + uint8_t buffer[2][1024]; + struct spa_pod_dynamic_builder b[2]; + spa_pod_dynamic_builder_init(&b[0], buffer[0], sizeof(buffer[0]), 2048); + spa_pod_dynamic_builder_init(&b[1], buffer[1], sizeof(buffer[1]), 2048); const struct spa_pod *params[2]; char name[] = "xdpw-stream-XXXXXX"; @@ -489,7 +511,10 @@ void xdpw_pwr_stream_create(struct xdpw_screencast_instance *cast) { } cast->pwr_stream_state = false; - uint32_t param_count = build_formats(&b, cast, params); + struct spa_pod_builder *builder[2] = {&b[0].b, &b[1].b}; + uint32_t param_count = build_formats(builder, cast, params); + spa_pod_dynamic_builder_clean(&b[0]); + spa_pod_dynamic_builder_clean(&b[1]); pw_stream_add_listener(cast->stream, &cast->stream_listener, &pwr_stream_events, cast);