Create frame-capture backend framework
parent
e037e74756
commit
ffda3c164c
|
@ -0,0 +1,53 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct wl_output;
|
||||
|
||||
enum frame_capture_status {
|
||||
CAPTURE_STOPPED = 0,
|
||||
CAPTURE_IN_PROGRESS,
|
||||
CAPTURE_FAILED,
|
||||
CAPTURE_FATAL,
|
||||
CAPTURE_DONE,
|
||||
};
|
||||
|
||||
struct frame_capture {
|
||||
enum frame_capture_status status;
|
||||
|
||||
bool overlay_cursor;
|
||||
struct wl_output* wl_output;
|
||||
|
||||
void* userdata;
|
||||
void (*on_done)(struct frame_capture*);
|
||||
|
||||
struct {
|
||||
uint32_t fourcc_format;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t stride;
|
||||
} frame_info;
|
||||
|
||||
struct {
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} damage_hint;
|
||||
|
||||
struct {
|
||||
int (*start)(struct frame_capture*);
|
||||
void (*stop)(struct frame_capture*);
|
||||
} backend;
|
||||
};
|
||||
|
||||
static inline int frame_capture_start(struct frame_capture* self)
|
||||
{
|
||||
return self->backend.start(self);
|
||||
}
|
||||
|
||||
static inline void frame_capture_stop(struct frame_capture* self)
|
||||
{
|
||||
self->backend.stop(self);
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include "wlr-screencopy-unstable-v1.h"
|
||||
#include "frame-capture.h"
|
||||
|
||||
struct zwlr_screencopy_manager_v1;
|
||||
struct zwlr_screencopy_frame_v1;
|
||||
|
@ -17,6 +18,8 @@ enum screencopy_status {
|
|||
};
|
||||
|
||||
struct screencopy {
|
||||
struct frame_capture frame_capture;
|
||||
|
||||
struct wl_shm* wl_shm;
|
||||
struct wl_buffer* buffer;
|
||||
|
||||
|
@ -25,26 +28,6 @@ struct screencopy {
|
|||
|
||||
struct zwlr_screencopy_manager_v1* manager;
|
||||
struct zwlr_screencopy_frame_v1* frame;
|
||||
|
||||
bool overlay_cursor;
|
||||
struct wl_output* output;
|
||||
enum screencopy_status status;
|
||||
void (*on_done)(struct screencopy*);
|
||||
|
||||
enum wl_shm_format format;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t stride;
|
||||
|
||||
struct {
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} damage;
|
||||
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
int screencopy_start(struct screencopy* self);
|
||||
void screencopy_stop(struct screencopy* self);
|
||||
void screencopy_init(struct screencopy* self);
|
||||
|
|
42
src/main.c
42
src/main.c
|
@ -58,6 +58,7 @@ struct wayvnc {
|
|||
|
||||
struct dmabuf_capture dmabuf_backend;
|
||||
struct screencopy screencopy_backend;
|
||||
struct frame_capture* capture_backend;
|
||||
|
||||
uv_poll_t wayland_poller;
|
||||
uv_prepare_t flusher;
|
||||
|
@ -73,7 +74,7 @@ struct wayvnc {
|
|||
};
|
||||
|
||||
void on_capture_done(struct dmabuf_capture* capture);
|
||||
void on_screencopy_done(struct screencopy* capture);
|
||||
void on_screencopy_done(struct frame_capture* capture);
|
||||
|
||||
static void output_handle_geometry(void* data, struct wl_output* wl_output,
|
||||
int32_t x, int32_t y, int32_t phys_width,
|
||||
|
@ -243,8 +244,8 @@ static int init_wayland(struct wayvnc* self)
|
|||
self->dmabuf_backend.on_done = on_capture_done;
|
||||
self->dmabuf_backend.userdata = self;
|
||||
|
||||
self->screencopy_backend.on_done = on_screencopy_done;
|
||||
self->screencopy_backend.userdata = self;
|
||||
self->screencopy_backend.frame_capture.on_done = on_screencopy_done;
|
||||
self->screencopy_backend.frame_capture.userdata = self;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -262,7 +263,8 @@ int wayvnc_select_first_output(struct wayvnc* self)
|
|||
wl_list_for_each(out, &self->outputs, link) {
|
||||
self->selected_output = out;
|
||||
self->dmabuf_backend.output = out->wl_output;
|
||||
self->screencopy_backend.output = out->wl_output;
|
||||
self->screencopy_backend.frame_capture.wl_output
|
||||
= out->wl_output;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -359,7 +361,7 @@ int init_nvnc(struct wayvnc* self, const char* addr, uint16_t port)
|
|||
|
||||
int wayvnc_start_capture(struct wayvnc* self)
|
||||
{
|
||||
return screencopy_start(&self->screencopy_backend);
|
||||
return frame_capture_start(self->capture_backend);
|
||||
// return dmabuf_capture_start(&self->dmabuf_backend);
|
||||
}
|
||||
|
||||
|
@ -388,10 +390,10 @@ void wayvnc_update_vnc(struct wayvnc* self, struct nvnc_fb* fb)
|
|||
self->current_fb = fb;
|
||||
|
||||
if (self->last_fb) {
|
||||
uint32_t hint_x = self->screencopy_backend.damage.x;
|
||||
uint32_t hint_y = self->screencopy_backend.damage.y;
|
||||
uint32_t hint_width = self->screencopy_backend.damage.width;
|
||||
uint32_t hint_height = self->screencopy_backend.damage.height;
|
||||
uint32_t hint_x = self->capture_backend->damage_hint.x;
|
||||
uint32_t hint_y = self->capture_backend->damage_hint.y;
|
||||
uint32_t hint_width = self->capture_backend->damage_hint.width;
|
||||
uint32_t hint_height = self->capture_backend->damage_hint.height;
|
||||
|
||||
nvnc_check_damage(self->current_fb, self->last_fb, hint_x,
|
||||
hint_y, hint_width, hint_height,
|
||||
|
@ -428,9 +430,10 @@ void wayvnc_process_screen(struct wayvnc* self)
|
|||
uint32_t format = fourcc_from_gl_format(self->renderer.read_format);
|
||||
|
||||
void* pixels = self->screencopy_backend.pixels;
|
||||
uint32_t width = self->screencopy_backend.width;
|
||||
uint32_t height = self->screencopy_backend.height;
|
||||
uint32_t stride = self->screencopy_backend.stride;
|
||||
|
||||
uint32_t width = self->capture_backend->frame_info.width;
|
||||
uint32_t height = self->capture_backend->frame_info.height;
|
||||
uint32_t stride = self->capture_backend->frame_info.stride;
|
||||
|
||||
struct nvnc_fb* fb = nvnc_fb_new(width, height, format);
|
||||
void* addr = nvnc_fb_get_addr(fb);
|
||||
|
@ -468,24 +471,26 @@ void on_capture_done(struct dmabuf_capture* capture)
|
|||
}
|
||||
}
|
||||
|
||||
void on_screencopy_done(struct screencopy* capture)
|
||||
void on_screencopy_done(struct frame_capture* capture)
|
||||
{
|
||||
struct wayvnc* self = capture->userdata;
|
||||
|
||||
switch (capture->status) {
|
||||
case SCREENCOPY_STATUS_CAPTURING:
|
||||
case CAPTURE_STOPPED:
|
||||
break;
|
||||
case SCREENCOPY_STATUS_FATAL:
|
||||
case CAPTURE_IN_PROGRESS:
|
||||
break;
|
||||
case CAPTURE_FATAL:
|
||||
log_error("Fatal error while capturing. Exiting...\n");
|
||||
wayvnc_exit();
|
||||
break;
|
||||
case SCREENCOPY_STATUS_FAILED:
|
||||
case CAPTURE_FAILED:
|
||||
if (wayvnc_start_capture(self) < 0) {
|
||||
log_error("Failed to start capture. Exiting...\n");
|
||||
wayvnc_exit();
|
||||
}
|
||||
break;
|
||||
case SCREENCOPY_STATUS_DONE:
|
||||
case CAPTURE_DONE:
|
||||
self->n_frames++;
|
||||
wayvnc_process_screen(self);
|
||||
break;
|
||||
|
@ -526,6 +531,9 @@ int main(int argc, char* argv[])
|
|||
if (init_nvnc(&self, "0.0.0.0", 5900) < 0)
|
||||
goto nvnc_failure;
|
||||
|
||||
screencopy_init(&self.screencopy_backend);
|
||||
self.capture_backend = &self.screencopy_backend.frame_capture;
|
||||
|
||||
if (wayvnc_start_capture(&self) < 0)
|
||||
goto capture_failure;
|
||||
|
||||
|
|
|
@ -20,10 +20,20 @@
|
|||
#include <stdbool.h>
|
||||
#include <sys/mman.h>
|
||||
#include <wayland-client.h>
|
||||
#include <libdrm/drm_fourcc.h>
|
||||
|
||||
#include "shm.h"
|
||||
#include "screencopy.h"
|
||||
|
||||
static uint32_t fourcc_from_wl_shm(enum wl_shm_format in)
|
||||
{
|
||||
switch (in) {
|
||||
case WL_SHM_FORMAT_ARGB8888: return DRM_FORMAT_ARGB8888;
|
||||
case WL_SHM_FORMAT_XRGB8888: return DRM_FORMAT_XRGB8888;
|
||||
default: return in;
|
||||
}
|
||||
}
|
||||
|
||||
static int screencopy_buffer_init(struct screencopy* self,
|
||||
enum wl_shm_format format, uint32_t width,
|
||||
uint32_t height, uint32_t stride)
|
||||
|
@ -66,8 +76,10 @@ mmap_failure:
|
|||
return -1;
|
||||
}
|
||||
|
||||
void screencopy_stop(struct screencopy* self)
|
||||
static void screencopy_stop(struct frame_capture* fc)
|
||||
{
|
||||
struct screencopy* self = (void*)fc;
|
||||
|
||||
if (self->frame) {
|
||||
zwlr_screencopy_frame_v1_destroy(self->frame);
|
||||
self->frame = NULL;
|
||||
|
@ -82,15 +94,16 @@ static void screencopy_buffer(void* data,
|
|||
struct screencopy* self = data;
|
||||
|
||||
if (screencopy_buffer_init(self, format, width, height, stride) < 0) {
|
||||
self->status = SCREENCOPY_STATUS_FATAL;
|
||||
screencopy_stop(self);
|
||||
self->on_done(self);
|
||||
self->frame_capture.status = CAPTURE_FATAL;
|
||||
screencopy_stop(&self->frame_capture);
|
||||
self->frame_capture.on_done(&self->frame_capture);
|
||||
}
|
||||
|
||||
self->format = format;
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
self->stride = stride;
|
||||
self->frame_capture.frame_info.fourcc_format =
|
||||
fourcc_from_wl_shm(format);
|
||||
self->frame_capture.frame_info.width = width;
|
||||
self->frame_capture.frame_info.height = height;
|
||||
self->frame_capture.frame_info.stride = stride;
|
||||
|
||||
zwlr_screencopy_frame_v1_copy_with_damage(self->frame, self->buffer);
|
||||
}
|
||||
|
@ -115,18 +128,21 @@ static void screencopy_ready(void* data,
|
|||
(void)nsec;
|
||||
|
||||
struct screencopy* self = data;
|
||||
screencopy_stop(self);
|
||||
self->status = SCREENCOPY_STATUS_DONE;
|
||||
self->on_done(self);
|
||||
|
||||
screencopy_stop(&self->frame_capture);
|
||||
|
||||
self->frame_capture.status = CAPTURE_DONE;
|
||||
self->frame_capture.on_done(&self->frame_capture);
|
||||
}
|
||||
|
||||
static void screencopy_failed(void* data,
|
||||
struct zwlr_screencopy_frame_v1* frame)
|
||||
{
|
||||
struct screencopy* self = data;
|
||||
screencopy_stop(self);
|
||||
self->status = SCREENCOPY_STATUS_FAILED;
|
||||
self->on_done(self);
|
||||
|
||||
screencopy_stop(&self->frame_capture);
|
||||
self->frame_capture.status = CAPTURE_FAILED;
|
||||
self->frame_capture.on_done(&self->frame_capture);
|
||||
}
|
||||
|
||||
static void screencopy_damage(void* data,
|
||||
|
@ -136,14 +152,16 @@ static void screencopy_damage(void* data,
|
|||
{
|
||||
struct screencopy* self = data;
|
||||
|
||||
self->damage.x = x;
|
||||
self->damage.y = y;
|
||||
self->damage.width = width;
|
||||
self->damage.height = height;
|
||||
self->frame_capture.damage_hint.x = x;
|
||||
self->frame_capture.damage_hint.y = y;
|
||||
self->frame_capture.damage_hint.width = width;
|
||||
self->frame_capture.damage_hint.height = height;
|
||||
}
|
||||
|
||||
int screencopy_start(struct screencopy* self)
|
||||
static int screencopy_start(struct frame_capture* fc)
|
||||
{
|
||||
struct screencopy* self = (void*)fc;
|
||||
|
||||
static const struct zwlr_screencopy_frame_v1_listener frame_listener = {
|
||||
.buffer = screencopy_buffer,
|
||||
.flags = screencopy_flags,
|
||||
|
@ -154,14 +172,20 @@ int screencopy_start(struct screencopy* self)
|
|||
|
||||
self->frame =
|
||||
zwlr_screencopy_manager_v1_capture_output(self->manager,
|
||||
self->overlay_cursor,
|
||||
self->output);
|
||||
fc->overlay_cursor,
|
||||
fc->wl_output);
|
||||
if (!self->frame)
|
||||
return -1;
|
||||
|
||||
zwlr_screencopy_frame_v1_add_listener(self->frame, &frame_listener,
|
||||
self);
|
||||
|
||||
self->status = SCREENCOPY_STATUS_CAPTURING;
|
||||
fc->status = CAPTURE_IN_PROGRESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void screencopy_init(struct screencopy* self)
|
||||
{
|
||||
self->frame_capture.backend.start = screencopy_start;
|
||||
self->frame_capture.backend.stop = screencopy_stop;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue