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