mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-22 21:05:58 +01:00
examples/dmabuf-capture: simplify event loop and fix style
This commit is contained in:
parent
85b6b4b0c8
commit
70d324a0f9
1 changed files with 72 additions and 91 deletions
|
@ -1,19 +1,17 @@
|
||||||
#define _XOPEN_SOURCE 700
|
#define _XOPEN_SOURCE 700
|
||||||
#define _POSIX_C_SOURCE 199309L
|
#define _POSIX_C_SOURCE 199309L
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/display.h>
|
||||||
|
#include <libavutil/hwcontext_drm.h>
|
||||||
|
#include <libavutil/pixdesc.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include "wlr-export-dmabuf-unstable-v1-client-protocol.h"
|
#include "wlr-export-dmabuf-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
#include <libavutil/pixdesc.h>
|
|
||||||
#include <libavutil/display.h>
|
|
||||||
#include <libavutil/hwcontext_drm.h>
|
|
||||||
|
|
||||||
struct wayland_output {
|
struct wayland_output {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
@ -96,10 +94,10 @@ static void output_handle_scale(void* data, struct wl_output *wl_output,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_output_listener output_listener = {
|
static const struct wl_output_listener output_listener = {
|
||||||
output_handle_geometry,
|
.geometry = output_handle_geometry,
|
||||||
output_handle_mode,
|
.mode = output_handle_mode,
|
||||||
output_handle_done,
|
.done = output_handle_done,
|
||||||
output_handle_scale,
|
.scale = output_handle_scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void registry_handle_add(void *data, struct wl_registry *reg,
|
static void registry_handle_add(void *data, struct wl_registry *reg,
|
||||||
|
@ -127,15 +125,16 @@ static void remove_output(struct wayland_output *out) {
|
||||||
av_free(out->make);
|
av_free(out->make);
|
||||||
av_free(out->model);
|
av_free(out->model);
|
||||||
av_free(out);
|
av_free(out);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wayland_output *find_output(struct capture_context *ctx,
|
static struct wayland_output *find_output(struct capture_context *ctx,
|
||||||
struct wl_output *out, uint32_t id) {
|
struct wl_output *out, uint32_t id) {
|
||||||
struct wayland_output *output, *tmp;
|
struct wayland_output *output, *tmp;
|
||||||
wl_list_for_each_safe(output, tmp, &ctx->output_list, link)
|
wl_list_for_each_safe(output, tmp, &ctx->output_list, link) {
|
||||||
if ((output->output == out) || (output->id == id))
|
if ((output->output == out) || (output->id == id)) {
|
||||||
return output;
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,8 +144,8 @@ static void registry_handle_remove(void *data, struct wl_registry *reg,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_registry_listener registry_listener = {
|
static const struct wl_registry_listener registry_listener = {
|
||||||
registry_handle_add,
|
.global = registry_handle_add,
|
||||||
registry_handle_remove,
|
.global_remove = registry_handle_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void frame_free(void *opaque, uint8_t *data) {
|
static void frame_free(void *opaque, uint8_t *data) {
|
||||||
|
@ -421,30 +420,31 @@ static void frame_cancel(void *data, struct zwlr_export_dmabuf_frame_v1 *frame,
|
||||||
struct capture_context *ctx = data;
|
struct capture_context *ctx = data;
|
||||||
av_log(ctx, AV_LOG_WARNING, "Frame cancelled!\n");
|
av_log(ctx, AV_LOG_WARNING, "Frame cancelled!\n");
|
||||||
av_frame_free(&ctx->current_frame);
|
av_frame_free(&ctx->current_frame);
|
||||||
if (reason != ZWLR_EXPORT_DMABUF_FRAME_V1_CANCEL_REASON_PERNAMENT)
|
if (reason == ZWLR_EXPORT_DMABUF_FRAME_V1_CANCEL_REASON_PERNAMENT) {
|
||||||
|
av_log(ctx, AV_LOG_ERROR, "Permanent failure, exiting\n");
|
||||||
|
ctx->err = 1;
|
||||||
|
} else {
|
||||||
register_cb(ctx);
|
register_cb(ctx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct zwlr_export_dmabuf_frame_v1_listener frame_listener = {
|
static const struct zwlr_export_dmabuf_frame_v1_listener frame_listener = {
|
||||||
frame_start,
|
.frame = frame_start,
|
||||||
frame_object,
|
.object = frame_object,
|
||||||
frame_plane,
|
.plane = frame_plane,
|
||||||
frame_ready,
|
.ready = frame_ready,
|
||||||
frame_cancel,
|
.cancel = frame_cancel,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void register_cb(struct capture_context *ctx)
|
static void register_cb(struct capture_context *ctx) {
|
||||||
{
|
ctx->frame_callback = zwlr_export_dmabuf_manager_v1_capture_output(
|
||||||
ctx->frame_callback =
|
ctx->export_manager, 0, ctx->target_output);
|
||||||
zwlr_export_dmabuf_manager_v1_capture_output(ctx->export_manager, 0,
|
|
||||||
ctx->target_output);
|
|
||||||
|
|
||||||
zwlr_export_dmabuf_frame_v1_add_listener(ctx->frame_callback,
|
zwlr_export_dmabuf_frame_v1_add_listener(ctx->frame_callback,
|
||||||
&frame_listener, ctx);
|
&frame_listener, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_lavu_hwcontext(struct capture_context *ctx) {
|
static int init_lavu_hwcontext(struct capture_context *ctx) {
|
||||||
|
|
||||||
/* DRM hwcontext */
|
/* DRM hwcontext */
|
||||||
ctx->drm_device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
|
ctx->drm_device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
|
||||||
if (!ctx->drm_device_ref)
|
if (!ctx->drm_device_ref)
|
||||||
|
@ -471,8 +471,7 @@ static int init_lavu_hwcontext(struct capture_context *ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_hwframe_ctx(struct capture_context *ctx,
|
static int set_hwframe_ctx(struct capture_context *ctx,
|
||||||
AVBufferRef *hw_device_ctx)
|
AVBufferRef *hw_device_ctx) {
|
||||||
{
|
|
||||||
AVHWFramesContext *frames_ctx = NULL;
|
AVHWFramesContext *frames_ctx = NULL;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
@ -553,8 +552,9 @@ static int init_encoding(struct capture_context *ctx) {
|
||||||
ctx->avctx->width = find_output(ctx, ctx->target_output, 0)->width;
|
ctx->avctx->width = find_output(ctx, ctx->target_output, 0)->width;
|
||||||
ctx->avctx->height = find_output(ctx, ctx->target_output, 0)->height;
|
ctx->avctx->height = find_output(ctx, ctx->target_output, 0)->height;
|
||||||
|
|
||||||
if (ctx->avf->oformat->flags & AVFMT_GLOBALHEADER)
|
if (ctx->avf->oformat->flags & AVFMT_GLOBALHEADER) {
|
||||||
ctx->avctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
ctx->avctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||||
|
}
|
||||||
|
|
||||||
st->id = 0;
|
st->id = 0;
|
||||||
st->time_base = ctx->avctx->time_base;
|
st->time_base = ctx->avctx->time_base;
|
||||||
|
@ -562,8 +562,9 @@ static int init_encoding(struct capture_context *ctx) {
|
||||||
|
|
||||||
/* Init hw frames context */
|
/* Init hw frames context */
|
||||||
err = set_hwframe_ctx(ctx, ctx->mapped_device_ref);
|
err = set_hwframe_ctx(ctx, ctx->mapped_device_ref);
|
||||||
if (err)
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
err = avcodec_open2(ctx->avctx, out_codec, &ctx->encoder_opts);
|
err = avcodec_open2(ctx->avctx, out_codec, &ctx->encoder_opts);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -616,45 +617,21 @@ static int main_loop(struct capture_context *ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
err = init_lavu_hwcontext(ctx);
|
err = init_lavu_hwcontext(ctx);
|
||||||
if (err)
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
err = init_encoding(ctx);
|
err = init_encoding(ctx);
|
||||||
if (err)
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Start the frame callback */
|
/* Start the frame callback */
|
||||||
register_cb(ctx);
|
register_cb(ctx);
|
||||||
|
|
||||||
while (!ctx->err && ctx->quit < 2) {
|
while (wl_display_dispatch(ctx->display) != -1 && !ctx->err &&
|
||||||
while (wl_display_prepare_read(ctx->display) != 0) {
|
ctx->quit < 2) {
|
||||||
wl_display_dispatch_pending(ctx->display);
|
// This space intentionally left blank
|
||||||
}
|
|
||||||
|
|
||||||
wl_display_flush(ctx->display);
|
|
||||||
|
|
||||||
struct pollfd fds[1] = {
|
|
||||||
{ .fd = wl_display_get_fd(ctx->display), .events = POLLIN },
|
|
||||||
};
|
|
||||||
|
|
||||||
poll(fds, 1, -1);
|
|
||||||
|
|
||||||
if (!(fds[0].revents & POLLIN)) {
|
|
||||||
wl_display_cancel_read(ctx->display);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
|
|
||||||
av_log(ctx, AV_LOG_ERROR, "Error occurred on the display fd!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fds[0].revents & POLLIN) {
|
|
||||||
if (wl_display_read_events(ctx->display) < 0) {
|
|
||||||
av_log(ctx, AV_LOG_ERROR, "Failed to read Wayland events!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wl_display_dispatch_pending(ctx->display);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = av_write_trailer(ctx->avf);
|
err = av_write_trailer(ctx->avf);
|
||||||
|
@ -705,8 +682,9 @@ int main(int argc, char *argv[]) {
|
||||||
});
|
});
|
||||||
|
|
||||||
err = init(&ctx);
|
err = init(&ctx);
|
||||||
if (err)
|
if (err) {
|
||||||
goto end;
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
struct wayland_output *o, *tmp_o;
|
struct wayland_output *o, *tmp_o;
|
||||||
wl_list_for_each_reverse_safe(o, tmp_o, &ctx.output_list, link) {
|
wl_list_for_each_reverse_safe(o, tmp_o, &ctx.output_list, link) {
|
||||||
|
@ -742,8 +720,9 @@ int main(int argc, char *argv[]) {
|
||||||
av_dict_set(&ctx.encoder_opts, "preset", "veryfast", 0);
|
av_dict_set(&ctx.encoder_opts, "preset", "veryfast", 0);
|
||||||
|
|
||||||
err = main_loop(&ctx);
|
err = main_loop(&ctx);
|
||||||
if (err)
|
if (err) {
|
||||||
goto end;
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
uninit(&ctx);
|
uninit(&ctx);
|
||||||
|
@ -752,11 +731,13 @@ end:
|
||||||
|
|
||||||
static void uninit(struct capture_context *ctx) {
|
static void uninit(struct capture_context *ctx) {
|
||||||
struct wayland_output *output, *tmp_o;
|
struct wayland_output *output, *tmp_o;
|
||||||
wl_list_for_each_safe(output, tmp_o, &ctx->output_list, link)
|
wl_list_for_each_safe(output, tmp_o, &ctx->output_list, link) {
|
||||||
remove_output(output);
|
remove_output(output);
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->export_manager)
|
if (ctx->export_manager) {
|
||||||
zwlr_export_dmabuf_manager_v1_destroy(ctx->export_manager);
|
zwlr_export_dmabuf_manager_v1_destroy(ctx->export_manager);
|
||||||
|
}
|
||||||
|
|
||||||
av_buffer_unref(&ctx->drm_frames_ref);
|
av_buffer_unref(&ctx->drm_frames_ref);
|
||||||
av_buffer_unref(&ctx->drm_device_ref);
|
av_buffer_unref(&ctx->drm_device_ref);
|
||||||
|
|
Loading…
Reference in a new issue