mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-26 07:55:58 +01:00
screencast: don't use the PipeWire event to trigger screencast
Using the on_process event of the PipeWire can create a race condition when a previous started screencast hasn't finished before the next event.
This commit is contained in:
parent
699e6ecf77
commit
10a07f7e90
4 changed files with 21 additions and 48 deletions
|
@ -6,8 +6,6 @@
|
||||||
#define XDPW_PWR_BUFFERS 4
|
#define XDPW_PWR_BUFFERS 4
|
||||||
#define XDPW_PWR_ALIGN 16
|
#define XDPW_PWR_ALIGN 16
|
||||||
|
|
||||||
void xdpw_pwr_trigger_process(struct xdpw_screencast_instance *cast);
|
|
||||||
bool xdpw_pwr_is_driving(struct xdpw_screencast_instance *cast);
|
|
||||||
void xdpw_pwr_dequeue_buffer(struct xdpw_screencast_instance *cast);
|
void xdpw_pwr_dequeue_buffer(struct xdpw_screencast_instance *cast);
|
||||||
void xdpw_pwr_enqueue_buffer(struct xdpw_screencast_instance *cast);
|
void xdpw_pwr_enqueue_buffer(struct xdpw_screencast_instance *cast);
|
||||||
void pwr_update_stream_param(struct xdpw_screencast_instance *cast);
|
void pwr_update_stream_param(struct xdpw_screencast_instance *cast);
|
||||||
|
|
|
@ -31,6 +31,7 @@ enum xdpw_chooser_types {
|
||||||
|
|
||||||
enum xdpw_frame_state {
|
enum xdpw_frame_state {
|
||||||
XDPW_FRAME_STATE_NONE,
|
XDPW_FRAME_STATE_NONE,
|
||||||
|
XDPW_FRAME_STATE_STARTED,
|
||||||
XDPW_FRAME_STATE_RENEG,
|
XDPW_FRAME_STATE_RENEG,
|
||||||
XDPW_FRAME_STATE_FAILED,
|
XDPW_FRAME_STATE_FAILED,
|
||||||
XDPW_FRAME_STATE_SUCCESS,
|
XDPW_FRAME_STATE_SUCCESS,
|
||||||
|
|
|
@ -44,14 +44,6 @@ static struct spa_pod *build_format(struct spa_pod_builder *b, enum spa_video_fo
|
||||||
return spa_pod_builder_pop(b, &f[0]);
|
return spa_pod_builder_pop(b, &f[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pwr_handle_stream_process(void *data) {
|
|
||||||
struct xdpw_screencast_instance *cast = data;
|
|
||||||
|
|
||||||
logprint(TRACE, "pipewire: stream process");
|
|
||||||
|
|
||||||
xdpw_wlr_frame_start(cast);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pwr_handle_stream_state_changed(void *data,
|
static void pwr_handle_stream_state_changed(void *data,
|
||||||
enum pw_stream_state old, enum pw_stream_state state, const char *error) {
|
enum pw_stream_state old, enum pw_stream_state state, const char *error) {
|
||||||
struct xdpw_screencast_instance *cast = data;
|
struct xdpw_screencast_instance *cast = data;
|
||||||
|
@ -64,7 +56,7 @@ static void pwr_handle_stream_state_changed(void *data,
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case PW_STREAM_STATE_STREAMING:
|
case PW_STREAM_STATE_STREAMING:
|
||||||
cast->pwr_stream_state = true;
|
cast->pwr_stream_state = true;
|
||||||
if (!cast->wlr_frame) {
|
if (cast->frame_state == XDPW_FRAME_STATE_NONE) {
|
||||||
xdpw_wlr_frame_start(cast);
|
xdpw_wlr_frame_start(cast);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -184,17 +176,8 @@ static const struct pw_stream_events pwr_stream_events = {
|
||||||
.param_changed = pwr_handle_stream_param_changed,
|
.param_changed = pwr_handle_stream_param_changed,
|
||||||
.add_buffer = pwr_handle_stream_add_buffer,
|
.add_buffer = pwr_handle_stream_add_buffer,
|
||||||
.remove_buffer = pwr_handle_stream_remove_buffer,
|
.remove_buffer = pwr_handle_stream_remove_buffer,
|
||||||
.process = pwr_handle_stream_process,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void xdpw_pwr_trigger_process(struct xdpw_screencast_instance *cast) {
|
|
||||||
pw_stream_trigger_process(cast->stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool xdpw_pwr_is_driving(struct xdpw_screencast_instance *cast) {
|
|
||||||
return pw_stream_is_driving(cast->stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
void xdpw_pwr_dequeue_buffer(struct xdpw_screencast_instance *cast) {
|
void xdpw_pwr_dequeue_buffer(struct xdpw_screencast_instance *cast) {
|
||||||
logprint(TRACE, "pipewire: dequeueing buffer");
|
logprint(TRACE, "pipewire: dequeueing buffer");
|
||||||
|
|
||||||
|
|
|
@ -32,19 +32,6 @@ void xdpw_wlr_frame_finish(struct xdpw_screencast_instance *cast) {
|
||||||
|
|
||||||
wlr_frame_free(cast);
|
wlr_frame_free(cast);
|
||||||
|
|
||||||
if (!cast->pwr_stream_state) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we have a buffer
|
|
||||||
if (cast->current_frame.current_pw_buffer) {
|
|
||||||
xdpw_pwr_enqueue_buffer(cast);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cast->frame_state == XDPW_FRAME_STATE_RENEG) {
|
|
||||||
pwr_update_stream_param(cast);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cast->quit || cast->err) {
|
if (cast->quit || cast->err) {
|
||||||
// TODO: revisit the exit condition (remove quit?)
|
// TODO: revisit the exit condition (remove quit?)
|
||||||
// and clean up sessions that still exist if err
|
// and clean up sessions that still exist if err
|
||||||
|
@ -53,19 +40,29 @@ void xdpw_wlr_frame_finish(struct xdpw_screencast_instance *cast) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cast->pwr_stream_state && xdpw_pwr_is_driving(cast)) {
|
// Check if we have a buffer
|
||||||
|
if (cast->current_frame.current_pw_buffer) {
|
||||||
|
xdpw_pwr_enqueue_buffer(cast);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cast->pwr_stream_state) {
|
||||||
|
cast->frame_state = XDPW_FRAME_STATE_NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cast->frame_state == XDPW_FRAME_STATE_RENEG) {
|
||||||
|
pwr_update_stream_param(cast);
|
||||||
|
}
|
||||||
|
|
||||||
if (cast->frame_state == XDPW_FRAME_STATE_SUCCESS) {
|
if (cast->frame_state == XDPW_FRAME_STATE_SUCCESS) {
|
||||||
uint64_t delay_ns = fps_limit_measure_end(&cast->fps_limit, cast->framerate);
|
uint64_t delay_ns = fps_limit_measure_end(&cast->fps_limit, cast->framerate);
|
||||||
if (delay_ns > 0) {
|
if (delay_ns > 0) {
|
||||||
xdpw_add_timer(cast->ctx->state, delay_ns,
|
xdpw_add_timer(cast->ctx->state, delay_ns,
|
||||||
(xdpw_event_loop_timer_func_t) xdpw_pwr_trigger_process, cast);
|
(xdpw_event_loop_timer_func_t) xdpw_wlr_frame_start, cast);
|
||||||
} else {
|
return;
|
||||||
xdpw_pwr_trigger_process(cast);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
xdpw_pwr_trigger_process(cast);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
xdpw_wlr_frame_start(cast);
|
||||||
}
|
}
|
||||||
|
|
||||||
void xdpw_wlr_frame_start(struct xdpw_screencast_instance *cast) {
|
void xdpw_wlr_frame_start(struct xdpw_screencast_instance *cast) {
|
||||||
|
@ -81,11 +78,10 @@ void xdpw_wlr_frame_start(struct xdpw_screencast_instance *cast) {
|
||||||
|
|
||||||
if (!cast->current_frame.current_pw_buffer) {
|
if (!cast->current_frame.current_pw_buffer) {
|
||||||
logprint(WARN, "wlroots: failed to dequeue buffer");
|
logprint(WARN, "wlroots: failed to dequeue buffer");
|
||||||
// TODO: wait for next frame
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cast->frame_state = XDPW_FRAME_STATE_NONE;
|
cast->frame_state = XDPW_FRAME_STATE_STARTED;
|
||||||
xdpw_wlr_register_cb(cast);
|
xdpw_wlr_register_cb(cast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,11 +117,6 @@ static void wlr_frame_buffer_done(void *data,
|
||||||
struct xdpw_screencast_instance *cast = data;
|
struct xdpw_screencast_instance *cast = data;
|
||||||
|
|
||||||
logprint(TRACE, "wlroots: buffer_done event handler");
|
logprint(TRACE, "wlroots: buffer_done event handler");
|
||||||
if (!cast->pwr_stream_state) {
|
|
||||||
xdpw_wlr_frame_finish(cast);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cast->current_frame.current_pw_buffer) {
|
if (!cast->current_frame.current_pw_buffer) {
|
||||||
logprint(WARN, "wlroots: no current buffer");
|
logprint(WARN, "wlroots: no current buffer");
|
||||||
xdpw_wlr_frame_finish(cast);
|
xdpw_wlr_frame_finish(cast);
|
||||||
|
|
Loading…
Reference in a new issue