Remove frame-capture abstraction

pull/55/head
Andri Yngvason 2020-06-26 21:44:58 +00:00
parent b0ec79acf8
commit 2b522ee596
4 changed files with 84 additions and 163 deletions

View File

@ -1,77 +0,0 @@
/*
* Copyright (c) 2019 - 2020 Andri Yngvason
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
struct wl_output;
struct nvnc_fb;
struct renderer;
enum frame_capture_status {
CAPTURE_STOPPED = 0,
CAPTURE_IN_PROGRESS,
CAPTURE_FAILED,
CAPTURE_FATAL,
CAPTURE_DONE,
};
enum frame_capture_options {
CAPTURE_NOW = 1 << 0,
};
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 {
void (*render)(struct frame_capture*, struct renderer*,
struct nvnc_fb* fb);
int (*start)(struct frame_capture*, enum frame_capture_options);
void (*stop)(struct frame_capture*);
} backend;
};
static inline int frame_capture_start(struct frame_capture* self, enum frame_capture_options options)
{
return self->backend.start(self, options);
}
static inline void frame_capture_stop(struct frame_capture* self)
{
self->backend.stop(self);
}
static inline void frame_capture_render(struct frame_capture* self,
struct renderer* renderer,
struct nvnc_fb* fb)
{
return self->backend.render(self, renderer, fb);
}

View File

@ -19,7 +19,6 @@
#include <stdbool.h>
#include "wlr-screencopy-unstable-v1.h"
#include "frame-capture.h"
#include "smooth.h"
#include "buffer.h"
@ -32,14 +31,15 @@ struct aml_timer;
struct renderer;
enum screencopy_status {
SCREENCOPY_STATUS_CAPTURING = 0,
SCREENCOPY_STATUS_FATAL,
SCREENCOPY_STATUS_FAILED,
SCREENCOPY_STATUS_DONE,
SCREENCOPY_STOPPED = 0,
SCREENCOPY_IN_PROGRESS,
SCREENCOPY_FAILED,
SCREENCOPY_FATAL,
SCREENCOPY_DONE,
};
struct screencopy {
struct frame_capture frame_capture;
enum screencopy_status status;
struct wv_buffer_pool* pool;
struct wv_buffer* front;
@ -49,6 +49,9 @@ struct screencopy {
struct zwlr_screencopy_frame_v1* frame;
int version;
void* userdata;
void (*on_done)(struct screencopy*);
uint64_t last_time;
uint64_t start_time;
struct aml_timer* timer;
@ -56,6 +59,8 @@ struct screencopy {
struct smooth delay_smoother;
double delay;
bool is_immediate_copy;
bool overlay_cursor;
struct wl_output* wl_output;
uint32_t wl_shm_width, wl_shm_height, wl_shm_stride;
enum wl_shm_format wl_shm_format;
@ -67,3 +72,8 @@ struct screencopy {
void screencopy_init(struct screencopy* self);
void screencopy_destroy(struct screencopy* self);
int screencopy_start(struct screencopy* self);
int screencopy_start_immediate(struct screencopy* self);
void screencopy_stop(struct screencopy* self);

View File

@ -37,7 +37,6 @@
#include <gbm.h>
#include <xf86drm.h>
#include "frame-capture.h"
#include "wlr-screencopy-unstable-v1.h"
#include "wlr-virtual-pointer-unstable-v1.h"
#include "virtual-keyboard-unstable-v1.h"
@ -76,8 +75,7 @@ struct wayvnc {
const struct output* selected_output;
const struct seat* selected_seat;
struct screencopy screencopy_backend;
struct frame_capture* capture_backend;
struct screencopy screencopy;
struct pointer pointer_backend;
struct keyboard keyboard_backend;
@ -95,7 +93,7 @@ struct wayvnc {
};
void wayvnc_exit(struct wayvnc* self);
void on_capture_done(struct frame_capture* capture);
void on_capture_done(struct screencopy* sc);
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb);
struct wl_shm* wl_shm = NULL;
@ -136,11 +134,11 @@ static void registry_add(void* data, struct wl_registry* registry,
}
if (strcmp(interface, zwlr_screencopy_manager_v1_interface.name) == 0) {
self->screencopy_backend.manager =
self->screencopy.manager =
wl_registry_bind(registry, id,
&zwlr_screencopy_manager_v1_interface,
version);
self->screencopy_backend.version = version;
self->screencopy.version = version;
return;
}
@ -251,8 +249,8 @@ void wayvnc_destroy(struct wayvnc* self)
zwlr_virtual_pointer_manager_v1_destroy(self->pointer_manager);
pointer_destroy(&self->pointer_backend);
if (self->screencopy_backend.manager)
zwlr_screencopy_manager_v1_destroy(self->screencopy_backend.manager);
if (self->screencopy.manager)
zwlr_screencopy_manager_v1_destroy(self->screencopy.manager);
wl_display_disconnect(self->display);
}
@ -307,13 +305,13 @@ static int init_wayland(struct wayvnc* self)
wl_display_dispatch(self->display);
wl_display_roundtrip(self->display);
if (!self->screencopy_backend.manager) {
if (!self->screencopy.manager) {
log_error("Compositor doesn't support screencopy! Exiting.\n");
goto failure;
}
self->screencopy_backend.frame_capture.on_done = on_capture_done;
self->screencopy_backend.frame_capture.userdata = self;
self->screencopy.on_done = on_capture_done;
self->screencopy.userdata = self;
return 0;
@ -454,9 +452,14 @@ failure:
return -1;
}
int wayvnc_start_capture(struct wayvnc* self, enum frame_capture_options opt)
int wayvnc_start_capture(struct wayvnc* self)
{
return frame_capture_start(self->capture_backend, opt);
return screencopy_start(&self->screencopy);
}
int wayvnc_start_capture_immediate(struct wayvnc* self)
{
return screencopy_start_immediate(&self->screencopy);
}
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb)
@ -464,11 +467,11 @@ static void on_render(struct nvnc_display* display, struct nvnc_fb* fb)
struct nvnc* nvnc = nvnc_display_get_server(display);
struct wayvnc* self = nvnc_get_userdata(nvnc);
if (!self->screencopy_backend.back)
if (!self->screencopy.back)
return;
enum wl_output_transform transform = self->selected_output->transform;
wv_pixman_render(fb, self->screencopy_backend.back, transform,
wv_pixman_render(fb, self->screencopy.back, transform,
&self->current_damage);
pixman_region_clear(&self->current_damage);
}
@ -490,8 +493,8 @@ void wayvnc_process_frame(struct wayvnc* self)
nvnc_display_set_buffer(self->nvnc_display, self->buffer);
damage_refinery_init(&self->damage_refinery,
self->screencopy_backend.back->width,
self->screencopy_backend.back->height);
self->screencopy.back->width,
self->screencopy.back->height);
} else {
// TODO: Reallocate
assert(width == nvnc_fb_get_width(self->buffer));
@ -502,8 +505,8 @@ void wayvnc_process_frame(struct wayvnc* self)
pixman_region_init(&txdamage);
pixman_region_init(&refined);
damage_refine(&self->damage_refinery, &refined,
&self->screencopy_backend.back->damage,
self->screencopy_backend.back);
&self->screencopy.back->damage,
self->screencopy.back);
wv_region_transform(&txdamage, &refined,
self->selected_output->transform,
self->selected_output->width,
@ -513,32 +516,32 @@ void wayvnc_process_frame(struct wayvnc* self)
pixman_region_fini(&refined);
pixman_region_fini(&txdamage);
if (wayvnc_start_capture(self, 0) < 0) {
if (wayvnc_start_capture(self) < 0) {
log_error("Failed to start capture. Exiting...\n");
wayvnc_exit(self);
}
}
void on_capture_done(struct frame_capture* capture)
void on_capture_done(struct screencopy* sc)
{
struct wayvnc* self = capture->userdata;
struct wayvnc* self = sc->userdata;
switch (capture->status) {
case CAPTURE_STOPPED:
switch (sc->status) {
case SCREENCOPY_STOPPED:
break;
case CAPTURE_IN_PROGRESS:
case SCREENCOPY_IN_PROGRESS:
break;
case CAPTURE_FATAL:
case SCREENCOPY_FATAL:
log_error("Fatal error while capturing. Exiting...\n");
wayvnc_exit(self);
break;
case CAPTURE_FAILED:
if (wayvnc_start_capture(self, CAPTURE_NOW) < 0) {
case SCREENCOPY_FAILED:
if (wayvnc_start_capture_immediate(self) < 0) {
log_error("Failed to start capture. Exiting...\n");
wayvnc_exit(self);
}
break;
case CAPTURE_DONE:
case SCREENCOPY_DONE:
wayvnc_process_frame(self);
break;
}
@ -722,7 +725,7 @@ int main(int argc, char* argv[])
self.selected_output = out;
self.selected_seat = seat;
self.screencopy_backend.frame_capture.wl_output = out->wl_output;
self.screencopy.wl_output = out->wl_output;
self.keyboard_backend.virtual_keyboard =
zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(
@ -766,21 +769,19 @@ int main(int argc, char* argv[])
if (init_nvnc(&self, address, port) < 0)
goto nvnc_failure;
if (self.screencopy_backend.manager)
screencopy_init(&self.screencopy_backend);
if (self.screencopy.manager)
screencopy_init(&self.screencopy);
if (!self.screencopy_backend.manager) {
if (!self.screencopy.manager) {
log_error("screencopy is not supported by compositor\n");
goto capture_failure;
}
self.capture_backend = &self.screencopy_backend.frame_capture;
pixman_region_init(&self.current_damage);
self.capture_backend->overlay_cursor = overlay_cursor;
self.screencopy.overlay_cursor = overlay_cursor;
if (wayvnc_start_capture(&self, 0) < 0)
if (wayvnc_start_capture(&self) < 0)
goto capture_failure;
wl_display_dispatch(self.display);
@ -791,7 +792,7 @@ int main(int argc, char* argv[])
aml_dispatch(aml);
}
frame_capture_stop(self.capture_backend);
screencopy_stop(&self.screencopy);
if (self.buffer) nvnc_fb_unref(self.buffer);
@ -801,8 +802,8 @@ int main(int argc, char* argv[])
nvnc_close(self.nvnc);
if (zwp_linux_dmabuf)
zwp_linux_dmabuf_v1_destroy(zwp_linux_dmabuf);
if (self.screencopy_backend.manager)
screencopy_destroy(&self.screencopy_backend);
if (self.screencopy.manager)
screencopy_destroy(&self.screencopy);
wayvnc_destroy(&self);
aml_unref(aml);

View File

@ -26,7 +26,6 @@
#include "wlr-screencopy-unstable-v1.h"
#include "buffer.h"
#include "frame-capture.h"
#include "shm.h"
#include "screencopy.h"
#include "smooth.h"
@ -36,13 +35,12 @@
#define RATE_LIMIT 20.0 // Hz
#define DELAY_SMOOTHER_TIME_CONSTANT 0.5 // s
static void screencopy_stop(struct frame_capture* fc)
void screencopy_stop(struct screencopy* self)
{
struct screencopy* self = (void*)fc;
aml_stop(aml_get_default(), self->timer);
self->frame_capture.status = CAPTURE_STOPPED;
self->status = SCREENCOPY_STOPPED;
if (self->frame) {
zwlr_screencopy_frame_v1_destroy(self->frame);
@ -86,9 +84,9 @@ static void screencopy_buffer_done(void* data,
struct wv_buffer* buffer = wv_buffer_pool_acquire(self->pool);
if (!buffer) {
self->frame_capture.status = CAPTURE_FATAL;
screencopy_stop(&self->frame_capture);
self->frame_capture.on_done(&self->frame_capture);
screencopy_stop(self);
self->status = SCREENCOPY_FATAL;
self->on_done(self);
return;
}
@ -97,11 +95,6 @@ static void screencopy_buffer_done(void* data,
assert(!self->front);
self->front = buffer;
self->frame_capture.frame_info.fourcc_format = fourcc;
self->frame_capture.frame_info.width = width;
self->frame_capture.frame_info.height = height;
self->frame_capture.frame_info.stride = stride;
if (self->is_immediate_copy)
zwlr_screencopy_frame_v1_copy(self->frame, buffer->wl_buffer);
else
@ -150,7 +143,7 @@ static void screencopy_ready(void* data,
DTRACE_PROBE1(wayvnc, screencopy_ready, self);
screencopy_stop(&self->frame_capture);
screencopy_stop(self);
self->last_time = gettime_us();
@ -167,8 +160,8 @@ static void screencopy_ready(void* data,
wv_buffer_map(self->back);
self->frame_capture.status = CAPTURE_DONE;
self->frame_capture.on_done(&self->frame_capture);
self->status = SCREENCOPY_DONE;
self->on_done(self);
}
static void screencopy_failed(void* data,
@ -178,9 +171,9 @@ static void screencopy_failed(void* data,
DTRACE_PROBE1(wayvnc, screencopy_failed, self);
screencopy_stop(&self->frame_capture);
self->frame_capture.status = CAPTURE_FAILED;
self->frame_capture.on_done(&self->frame_capture);
screencopy_stop(self);
self->status = SCREENCOPY_FAILED;
self->on_done(self);
}
static void screencopy_damage(void* data,
@ -195,10 +188,8 @@ static void screencopy_damage(void* data,
wv_buffer_damage_rect(self->front, x, y, width, height);
}
static int screencopy__start_capture(struct frame_capture* fc)
static int screencopy__start_capture(struct screencopy* self)
{
struct screencopy* self = (void*)fc;
DTRACE_PROBE1(wayvnc, screencopy_start, self);
static const struct zwlr_screencopy_frame_v1_listener frame_listener = {
@ -213,10 +204,8 @@ static int screencopy__start_capture(struct frame_capture* fc)
self->start_time = gettime_us();
self->frame =
zwlr_screencopy_manager_v1_capture_output(self->manager,
fc->overlay_cursor,
fc->wl_output);
self->frame = zwlr_screencopy_manager_v1_capture_output(self->manager,
self->overlay_cursor, self->wl_output);
if (!self->frame)
return -1;
@ -229,38 +218,40 @@ static int screencopy__start_capture(struct frame_capture* fc)
static void screencopy__poll(void* obj)
{
struct screencopy* self = aml_get_userdata(obj);
struct frame_capture* fc = (struct frame_capture*)self;
screencopy__start_capture(fc);
screencopy__start_capture(self);
}
static int screencopy_start(struct frame_capture* fc,
enum frame_capture_options options)
static int screencopy__start(struct screencopy* self, bool is_immediate_copy)
{
struct screencopy* self = (void*)fc;
if (fc->status == CAPTURE_IN_PROGRESS)
if (self->status == SCREENCOPY_IN_PROGRESS)
return -1;
self->is_immediate_copy = !!(options & CAPTURE_NOW);
self->is_immediate_copy = is_immediate_copy;
uint64_t now = gettime_us();
double dt = (now - self->last_time) * 1.0e-6;
double time_left = (1.0 / RATE_LIMIT - dt - self->delay) * 1.0e3;
fc->status = CAPTURE_IN_PROGRESS;
self->status = SCREENCOPY_IN_PROGRESS;
if (time_left > 0) {
aml_set_duration(self->timer, time_left);
return aml_start(aml_get_default(), self->timer);
}
return screencopy__start_capture(fc);
return screencopy__start_capture(self);
}
static void screencopy_render(struct frame_capture* fc,
struct renderer* renderer, struct nvnc_fb* fb)
int screencopy_start(struct screencopy* self)
{
return screencopy__start(self, false);
}
int screencopy_start_immediate(struct screencopy* self)
{
return screencopy__start(self, true);
}
void screencopy_init(struct screencopy* self)
@ -272,10 +263,6 @@ void screencopy_init(struct screencopy* self)
assert(self->timer);
self->delay_smoother.time_constant = DELAY_SMOOTHER_TIME_CONSTANT;
self->frame_capture.backend.start = screencopy_start;
self->frame_capture.backend.stop = screencopy_stop;
self->frame_capture.backend.render = screencopy_render;
}
void screencopy_destroy(struct screencopy* self)