init
This commit is contained in:
118
include/args_parser.h
Normal file
118
include/args_parser.h
Normal file
@ -0,0 +1,118 @@
|
||||
#ifndef GSR_ARGS_PARSER_H
|
||||
#define GSR_ARGS_PARSER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "defs.h"
|
||||
#include "vec2.h"
|
||||
|
||||
typedef struct gsr_egl gsr_egl;
|
||||
|
||||
#define NUM_ARGS 32
|
||||
|
||||
typedef enum {
|
||||
GSR_CAPTURE_SOURCE_TYPE_WINDOW,
|
||||
GSR_CAPTURE_SOURCE_TYPE_FOCUSED_WINDOW,
|
||||
GSR_CAPTURE_SOURCE_TYPE_MONITOR,
|
||||
GSR_CAPTURE_SOURCE_TYPE_REGION,
|
||||
GSR_CAPTURE_SOURCE_TYPE_PORTAL,
|
||||
GSR_CAPTURE_SOURCE_TYPE_V4L2
|
||||
} CaptureSourceType;
|
||||
|
||||
typedef enum {
|
||||
ARG_TYPE_STRING,
|
||||
ARG_TYPE_BOOLEAN,
|
||||
ARG_TYPE_ENUM,
|
||||
ARG_TYPE_I64,
|
||||
ARG_TYPE_DOUBLE,
|
||||
} ArgType;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int value;
|
||||
} ArgEnum;
|
||||
|
||||
typedef struct {
|
||||
ArgType type;
|
||||
const char **values;
|
||||
int capacity_num_values;
|
||||
int num_values;
|
||||
|
||||
const char *key;
|
||||
bool optional;
|
||||
bool list;
|
||||
|
||||
const ArgEnum *enum_values;
|
||||
int num_enum_values;
|
||||
|
||||
int64_t integer_value_min;
|
||||
int64_t integer_value_max;
|
||||
|
||||
union {
|
||||
bool boolean;
|
||||
int enum_value;
|
||||
int64_t i64_value;
|
||||
double d_value;
|
||||
} typed_value;
|
||||
} Arg;
|
||||
|
||||
typedef struct {
|
||||
void (*version)(void *userdata);
|
||||
void (*info)(void *userdata);
|
||||
void (*list_audio_devices)(void *userdata);
|
||||
void (*list_application_audio)(void *userdata);
|
||||
void (*list_v4l2_devices)(void *userdata);
|
||||
void (*list_capture_options)(const char *card_path, void *userdata);
|
||||
} args_handlers;
|
||||
|
||||
typedef struct {
|
||||
Arg args[NUM_ARGS];
|
||||
|
||||
gsr_video_encoder_hardware video_encoder;
|
||||
gsr_pixel_format pixel_format;
|
||||
gsr_framerate_mode framerate_mode;
|
||||
gsr_color_range color_range;
|
||||
gsr_tune tune;
|
||||
gsr_video_codec video_codec;
|
||||
gsr_audio_codec audio_codec;
|
||||
gsr_bitrate_mode bitrate_mode;
|
||||
gsr_video_quality video_quality;
|
||||
gsr_replay_storage replay_storage;
|
||||
|
||||
const char *capture_source;
|
||||
const char *container_format;
|
||||
const char *filename;
|
||||
const char *replay_recording_directory;
|
||||
const char *portal_session_token_filepath;
|
||||
const char *recording_saved_script;
|
||||
bool verbose;
|
||||
bool gl_debug;
|
||||
bool fallback_cpu_encoding;
|
||||
bool record_cursor;
|
||||
bool date_folders;
|
||||
bool restore_portal_session;
|
||||
bool restart_replay_on_save;
|
||||
bool overclock;
|
||||
bool is_livestream;
|
||||
bool is_output_piped;
|
||||
bool low_latency_recording;
|
||||
bool very_old_gpu;
|
||||
int64_t video_bitrate;
|
||||
int64_t audio_bitrate;
|
||||
int64_t fps;
|
||||
int64_t replay_buffer_size_secs;
|
||||
double keyint;
|
||||
vec2i output_resolution;
|
||||
vec2i region_size;
|
||||
vec2i region_position;
|
||||
} args_parser;
|
||||
|
||||
/* |argv| is stored as a reference */
|
||||
bool args_parser_parse(args_parser *self, int argc, char **argv, const args_handlers *args_handlers, void *userdata);
|
||||
void args_parser_deinit(args_parser *self);
|
||||
|
||||
bool args_parser_validate_with_gl_info(args_parser *self, gsr_egl *egl);
|
||||
void args_parser_print_usage(void);
|
||||
Arg* args_parser_get_arg(args_parser *self, const char *arg_name);
|
||||
|
||||
#endif /* GSR_ARGS_PARSER_H */
|
||||
64
include/capture/capture.h
Normal file
64
include/capture/capture.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef GSR_CAPTURE_CAPTURE_H
|
||||
#define GSR_CAPTURE_CAPTURE_H
|
||||
|
||||
#include "../color_conversion.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct AVCodecContext AVCodecContext;
|
||||
typedef struct AVStream AVStream;
|
||||
typedef struct AVFrame AVFrame;
|
||||
typedef struct AVMasteringDisplayMetadata AVMasteringDisplayMetadata;
|
||||
typedef struct AVContentLightMetadata AVContentLightMetadata;
|
||||
typedef struct gsr_capture gsr_capture;
|
||||
typedef struct gsr_capture_metadata gsr_capture_metadata;
|
||||
|
||||
typedef enum {
|
||||
GSR_CAPTURE_ALIGN_START,
|
||||
GSR_CAPTURE_ALIGN_CENTER,
|
||||
GSR_CAPTURE_ALIGN_END
|
||||
} gsr_capture_alignment;
|
||||
|
||||
struct gsr_capture_metadata {
|
||||
// Size of the video
|
||||
vec2i video_size;
|
||||
// The captured output gets scaled to this size. By default this will be the same size as the captured target
|
||||
vec2i recording_size;
|
||||
vec2i position;
|
||||
int fps;
|
||||
gsr_capture_alignment halign;
|
||||
gsr_capture_alignment valign;
|
||||
gsr_flip flip;
|
||||
};
|
||||
|
||||
struct gsr_capture {
|
||||
/* These methods should not be called manually. Call gsr_capture_* instead. |capture_metadata->video_size| should be set by this function */
|
||||
int (*start)(gsr_capture *cap, gsr_capture_metadata *capture_metadata);
|
||||
void (*on_event)(gsr_capture *cap, gsr_egl *egl); /* can be NULL */
|
||||
void (*tick)(gsr_capture *cap); /* can be NULL. If there is an event then |on_event| is called before this */
|
||||
bool (*should_stop)(gsr_capture *cap, bool *err); /* can be NULL. If NULL, return false */
|
||||
bool (*capture_has_synchronous_task)(gsr_capture *cap); /* can be NULL. If this returns true then the time spent in |capture| is ignored for video/audio (capture is paused while the synchronous task happens) */
|
||||
void (*pre_capture)(gsr_capture *cap, gsr_capture_metadata *capture_metadata, gsr_color_conversion *color_conversion); /* can be NULL */
|
||||
int (*capture)(gsr_capture *cap, gsr_capture_metadata *capture_metadata, gsr_color_conversion *color_conversion); /* Return 0 if the frame was captured */
|
||||
bool (*uses_external_image)(gsr_capture *cap); /* can be NULL. If NULL, return false */
|
||||
bool (*set_hdr_metadata)(gsr_capture *cap, AVMasteringDisplayMetadata *mastering_display_metadata, AVContentLightMetadata *light_metadata); /* can be NULL. If NULL, return false */
|
||||
uint64_t (*get_window_id)(gsr_capture *cap); /* can be NULL. Returns 0 if unknown */
|
||||
bool (*is_damaged)(gsr_capture *cap); /* can be NULL */
|
||||
void (*clear_damage)(gsr_capture *cap); /* can be NULL */
|
||||
void (*destroy)(gsr_capture *cap);
|
||||
|
||||
void *priv; /* can be NULL */
|
||||
bool started;
|
||||
};
|
||||
|
||||
int gsr_capture_start(gsr_capture *cap, gsr_capture_metadata *capture_metadata);
|
||||
void gsr_capture_on_event(gsr_capture *cap, gsr_egl *egl);
|
||||
void gsr_capture_tick(gsr_capture *cap);
|
||||
bool gsr_capture_should_stop(gsr_capture *cap, bool *err);
|
||||
int gsr_capture_capture(gsr_capture *cap, gsr_capture_metadata *capture_metadata, gsr_color_conversion *color_conversion);
|
||||
bool gsr_capture_uses_external_image(gsr_capture *cap);
|
||||
bool gsr_capture_set_hdr_metadata(gsr_capture *cap, AVMasteringDisplayMetadata *mastering_display_metadata, AVContentLightMetadata *light_metadata);
|
||||
void gsr_capture_destroy(gsr_capture *cap);
|
||||
|
||||
#endif /* GSR_CAPTURE_CAPTURE_H */
|
||||
23
include/capture/kms.h
Normal file
23
include/capture/kms.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef GSR_CAPTURE_KMS_H
|
||||
#define GSR_CAPTURE_KMS_H
|
||||
|
||||
#include "capture.h"
|
||||
#include "../cursor.h"
|
||||
#include "../../kms/kms_shared.h"
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
gsr_cursor *x11_cursor;
|
||||
gsr_kms_response *kms_response;
|
||||
const char *display_to_capture; /* A copy is made of this */
|
||||
bool hdr;
|
||||
bool record_cursor;
|
||||
int fps;
|
||||
vec2i output_resolution;
|
||||
vec2i region_size;
|
||||
vec2i region_position;
|
||||
} gsr_capture_kms_params;
|
||||
|
||||
gsr_capture* gsr_capture_kms_create(const gsr_capture_kms_params *params);
|
||||
|
||||
#endif /* GSR_CAPTURE_KMS_H */
|
||||
20
include/capture/nvfbc.h
Normal file
20
include/capture/nvfbc.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef GSR_CAPTURE_NVFBC_H
|
||||
#define GSR_CAPTURE_NVFBC_H
|
||||
|
||||
#include "capture.h"
|
||||
#include "../vec2.h"
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
const char *display_to_capture; /* if this is "screen", then the entire x11 screen is captured (all displays). A copy is made of this */
|
||||
int fps;
|
||||
bool direct_capture;
|
||||
bool record_cursor;
|
||||
vec2i output_resolution;
|
||||
vec2i region_size;
|
||||
vec2i region_position;
|
||||
} gsr_capture_nvfbc_params;
|
||||
|
||||
gsr_capture* gsr_capture_nvfbc_create(const gsr_capture_nvfbc_params *params);
|
||||
|
||||
#endif /* GSR_CAPTURE_NVFBC_H */
|
||||
17
include/capture/portal.h
Normal file
17
include/capture/portal.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef GSR_CAPTURE_PORTAL_H
|
||||
#define GSR_CAPTURE_PORTAL_H
|
||||
|
||||
#include "capture.h"
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
bool record_cursor;
|
||||
bool restore_portal_session;
|
||||
/* If this is set to NULL then this defaults to $XDG_CONFIG_HOME/gpu-screen-recorder/restore_token ($XDG_CONFIG_HOME defaults to $HOME/.config) */
|
||||
const char *portal_session_token_filepath;
|
||||
vec2i output_resolution;
|
||||
} gsr_capture_portal_params;
|
||||
|
||||
gsr_capture* gsr_capture_portal_create(const gsr_capture_portal_params *params);
|
||||
|
||||
#endif /* GSR_CAPTURE_PORTAL_H */
|
||||
30
include/capture/v4l2.h
Normal file
30
include/capture/v4l2.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef GSR_CAPTURE_V4L2_H
|
||||
#define GSR_CAPTURE_V4L2_H
|
||||
|
||||
#include "capture.h"
|
||||
|
||||
typedef enum {
|
||||
GSR_CAPTURE_V4L2_PIXFMT_AUTO,
|
||||
GSR_CAPTURE_V4L2_PIXFMT_YUYV,
|
||||
GSR_CAPTURE_V4L2_PIXFMT_MJPEG
|
||||
} gsr_capture_v4l2_pixfmt;
|
||||
|
||||
typedef struct {
|
||||
bool yuyv;
|
||||
bool mjpeg;
|
||||
} gsr_capture_v4l2_supported_pixfmts;
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
vec2i output_resolution;
|
||||
const char *device_path;
|
||||
gsr_capture_v4l2_pixfmt pixfmt;
|
||||
int fps;
|
||||
} gsr_capture_v4l2_params;
|
||||
|
||||
gsr_capture* gsr_capture_v4l2_create(const gsr_capture_v4l2_params *params);
|
||||
|
||||
typedef void (*v4l2_devices_query_callback)(const char *path, gsr_capture_v4l2_supported_pixfmts supported_pixfmts, vec2i size, void *userdata);
|
||||
void gsr_capture_v4l2_list_devices(v4l2_devices_query_callback callback, void *userdata);
|
||||
|
||||
#endif /* GSR_CAPTURE_V4L2_H */
|
||||
19
include/capture/xcomposite.h
Normal file
19
include/capture/xcomposite.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef GSR_CAPTURE_XCOMPOSITE_H
|
||||
#define GSR_CAPTURE_XCOMPOSITE_H
|
||||
|
||||
#include "capture.h"
|
||||
#include "../vec2.h"
|
||||
#include "../cursor.h"
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
gsr_cursor *cursor;
|
||||
unsigned long window;
|
||||
bool follow_focused; /* If this is set then |window| is ignored */
|
||||
bool record_cursor;
|
||||
vec2i output_resolution;
|
||||
} gsr_capture_xcomposite_params;
|
||||
|
||||
gsr_capture* gsr_capture_xcomposite_create(const gsr_capture_xcomposite_params *params);
|
||||
|
||||
#endif /* GSR_CAPTURE_XCOMPOSITE_H */
|
||||
20
include/capture/ximage.h
Normal file
20
include/capture/ximage.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef GSR_CAPTURE_XIMAGE_H
|
||||
#define GSR_CAPTURE_XIMAGE_H
|
||||
|
||||
#include "capture.h"
|
||||
#include "../vec2.h"
|
||||
#include "../cursor.h"
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
gsr_cursor *cursor;
|
||||
const char *display_to_capture; /* A copy is made of this */
|
||||
bool record_cursor;
|
||||
vec2i output_resolution;
|
||||
vec2i region_size;
|
||||
vec2i region_position;
|
||||
} gsr_capture_ximage_params;
|
||||
|
||||
gsr_capture* gsr_capture_ximage_create(const gsr_capture_ximage_params *params);
|
||||
|
||||
#endif /* GSR_CAPTURE_XIMAGE_H */
|
||||
25
include/codec_query/codec_query.h
Normal file
25
include/codec_query/codec_query.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef GSR_CODEC_QUERY_H
|
||||
#define GSR_CODEC_QUERY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "../vec2.h"
|
||||
|
||||
typedef struct {
|
||||
bool supported;
|
||||
bool low_power;
|
||||
vec2i max_resolution;
|
||||
} gsr_supported_video_codec;
|
||||
|
||||
typedef struct {
|
||||
gsr_supported_video_codec h264;
|
||||
gsr_supported_video_codec hevc;
|
||||
gsr_supported_video_codec hevc_hdr;
|
||||
gsr_supported_video_codec hevc_10bit;
|
||||
gsr_supported_video_codec av1;
|
||||
gsr_supported_video_codec av1_hdr;
|
||||
gsr_supported_video_codec av1_10bit;
|
||||
gsr_supported_video_codec vp8;
|
||||
gsr_supported_video_codec vp9;
|
||||
} gsr_supported_video_codecs;
|
||||
|
||||
#endif /* GSR_CODEC_QUERY_H */
|
||||
8
include/codec_query/nvenc.h
Normal file
8
include/codec_query/nvenc.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef GSR_CODEC_QUERY_NVENC_H
|
||||
#define GSR_CODEC_QUERY_NVENC_H
|
||||
|
||||
#include "codec_query.h"
|
||||
|
||||
bool gsr_get_supported_video_codecs_nvenc(gsr_supported_video_codecs *video_codecs, bool cleanup);
|
||||
|
||||
#endif /* GSR_CODEC_QUERY_NVENC_H */
|
||||
8
include/codec_query/vaapi.h
Normal file
8
include/codec_query/vaapi.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef GSR_CODEC_QUERY_VAAPI_H
|
||||
#define GSR_CODEC_QUERY_VAAPI_H
|
||||
|
||||
#include "codec_query.h"
|
||||
|
||||
bool gsr_get_supported_video_codecs_vaapi(gsr_supported_video_codecs *video_codecs, const char *card_path, bool cleanup);
|
||||
|
||||
#endif /* GSR_CODEC_QUERY_VAAPI_H */
|
||||
8
include/codec_query/vulkan.h
Normal file
8
include/codec_query/vulkan.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef GSR_CODEC_QUERY_VULKAN_H
|
||||
#define GSR_CODEC_QUERY_VULKAN_H
|
||||
|
||||
#include "codec_query.h"
|
||||
|
||||
bool gsr_get_supported_video_codecs_vulkan(gsr_supported_video_codecs *video_codecs, const char *card_path, bool cleanup);
|
||||
|
||||
#endif /* GSR_CODEC_QUERY_VULKAN_H */
|
||||
78
include/color_conversion.h
Normal file
78
include/color_conversion.h
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef GSR_COLOR_CONVERSION_H
|
||||
#define GSR_COLOR_CONVERSION_H
|
||||
|
||||
#include "shader.h"
|
||||
#include "defs.h"
|
||||
#include "vec2.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define GSR_COLOR_CONVERSION_MAX_GRAPHICS_SHADERS 12
|
||||
#define GSR_COLOR_CONVERSION_MAX_FRAMEBUFFERS 2
|
||||
|
||||
typedef enum {
|
||||
GSR_SOURCE_COLOR_RGB,
|
||||
GSR_SOURCE_COLOR_BGR,
|
||||
GSR_SOURCE_COLOR_YUYV
|
||||
} gsr_source_color;
|
||||
|
||||
typedef enum {
|
||||
GSR_DESTINATION_COLOR_NV12, /* YUV420, BT709, 8-bit */
|
||||
GSR_DESTINATION_COLOR_P010, /* YUV420, BT2020, 10-bit */
|
||||
GSR_DESTINATION_COLOR_RGB8
|
||||
} gsr_destination_color;
|
||||
|
||||
typedef enum {
|
||||
GSR_ROT_0,
|
||||
GSR_ROT_90,
|
||||
GSR_ROT_180,
|
||||
GSR_ROT_270
|
||||
} gsr_rotation;
|
||||
|
||||
typedef enum {
|
||||
GSR_FLIP_NONE = 0,
|
||||
GSR_FLIP_HORIZONTAL = (1 << 0),
|
||||
GSR_FLIP_VERTICAL = (1 << 1)
|
||||
} gsr_flip;
|
||||
|
||||
typedef struct {
|
||||
int rotation_matrix;
|
||||
int offset;
|
||||
} gsr_color_graphics_uniforms;
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
|
||||
gsr_destination_color destination_color;
|
||||
|
||||
unsigned int destination_textures[2];
|
||||
vec2i destination_textures_size[2];
|
||||
int num_destination_textures;
|
||||
|
||||
gsr_color_range color_range;
|
||||
bool load_external_image_shader;
|
||||
} gsr_color_conversion_params;
|
||||
|
||||
typedef struct {
|
||||
gsr_color_conversion_params params;
|
||||
|
||||
gsr_color_graphics_uniforms graphics_uniforms[GSR_COLOR_CONVERSION_MAX_GRAPHICS_SHADERS];
|
||||
gsr_shader graphics_shaders[GSR_COLOR_CONVERSION_MAX_GRAPHICS_SHADERS];
|
||||
|
||||
unsigned int framebuffers[GSR_COLOR_CONVERSION_MAX_FRAMEBUFFERS];
|
||||
|
||||
unsigned int vertex_array_object_id;
|
||||
unsigned int vertex_buffer_object_id;
|
||||
|
||||
bool schedule_clear;
|
||||
} gsr_color_conversion;
|
||||
|
||||
int gsr_color_conversion_init(gsr_color_conversion *self, const gsr_color_conversion_params *params);
|
||||
void gsr_color_conversion_deinit(gsr_color_conversion *self);
|
||||
|
||||
void gsr_color_conversion_draw(gsr_color_conversion *self, unsigned int texture_id, vec2i destination_pos, vec2i destination_size, vec2i source_pos, vec2i source_size, vec2i texture_size, gsr_rotation rotation, gsr_flip flip, gsr_source_color source_color, bool external_texture);
|
||||
void gsr_color_conversion_clear(gsr_color_conversion *self);
|
||||
void gsr_color_conversion_read_destination_texture(gsr_color_conversion *self, int destination_texture_index, int x, int y, int width, int height, unsigned int color_format, unsigned int data_format, void *pixels);
|
||||
|
||||
gsr_rotation gsr_monitor_rotation_to_rotation(gsr_monitor_rotation monitor_rotation);
|
||||
|
||||
#endif /* GSR_COLOR_CONVERSION_H */
|
||||
108
include/cuda.h
Normal file
108
include/cuda.h
Normal file
@ -0,0 +1,108 @@
|
||||
#ifndef GSR_CUDA_H
|
||||
#define GSR_CUDA_H
|
||||
|
||||
#include "overclock.h"
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// To prevent hwcontext_cuda.h from including cuda.h
|
||||
#define CUDA_VERSION 11070
|
||||
|
||||
#define CU_CTX_SCHED_AUTO 0
|
||||
|
||||
#if defined(_WIN64) || defined(__LP64__)
|
||||
typedef unsigned long long CUdeviceptr_v2;
|
||||
#else
|
||||
typedef unsigned int CUdeviceptr_v2;
|
||||
#endif
|
||||
typedef CUdeviceptr_v2 CUdeviceptr;
|
||||
|
||||
typedef int CUresult;
|
||||
typedef int CUdevice_v1;
|
||||
typedef CUdevice_v1 CUdevice;
|
||||
typedef struct CUctx_st *CUcontext;
|
||||
typedef struct CUstream_st *CUstream;
|
||||
typedef struct CUarray_st *CUarray;
|
||||
|
||||
#define CUDA_SUCCESS 0
|
||||
|
||||
typedef enum CUgraphicsMapResourceFlags_enum {
|
||||
CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE = 0x00,
|
||||
CU_GRAPHICS_MAP_RESOURCE_FLAGS_READ_ONLY = 0x01,
|
||||
CU_GRAPHICS_MAP_RESOURCE_FLAGS_WRITE_DISCARD = 0x02
|
||||
} CUgraphicsMapResourceFlags;
|
||||
|
||||
typedef enum CUgraphicsRegisterFlags_enum {
|
||||
CU_GRAPHICS_REGISTER_FLAGS_NONE = 0x00,
|
||||
CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY = 0x01,
|
||||
CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD = 0x02,
|
||||
CU_GRAPHICS_REGISTER_FLAGS_SURFACE_LDST = 0x04,
|
||||
CU_GRAPHICS_REGISTER_FLAGS_TEXTURE_GATHER = 0x08
|
||||
} CUgraphicsRegisterFlags;
|
||||
|
||||
typedef enum CUmemorytype_enum {
|
||||
CU_MEMORYTYPE_HOST = 0x01, /**< Host memory */
|
||||
CU_MEMORYTYPE_DEVICE = 0x02, /**< Device memory */
|
||||
CU_MEMORYTYPE_ARRAY = 0x03, /**< Array memory */
|
||||
CU_MEMORYTYPE_UNIFIED = 0x04 /**< Unified device or host memory */
|
||||
} CUmemorytype;
|
||||
|
||||
typedef struct CUDA_MEMCPY2D_st {
|
||||
size_t srcXInBytes; /**< Source X in bytes */
|
||||
size_t srcY; /**< Source Y */
|
||||
|
||||
CUmemorytype srcMemoryType; /**< Source memory type (host, device, array) */
|
||||
const void *srcHost; /**< Source host pointer */
|
||||
CUdeviceptr srcDevice; /**< Source device pointer */
|
||||
CUarray srcArray; /**< Source array reference */
|
||||
size_t srcPitch; /**< Source pitch (ignored when src is array) */
|
||||
|
||||
size_t dstXInBytes; /**< Destination X in bytes */
|
||||
size_t dstY; /**< Destination Y */
|
||||
|
||||
CUmemorytype dstMemoryType; /**< Destination memory type (host, device, array) */
|
||||
void *dstHost; /**< Destination host pointer */
|
||||
CUdeviceptr dstDevice; /**< Destination device pointer */
|
||||
CUarray dstArray; /**< Destination array reference */
|
||||
size_t dstPitch; /**< Destination pitch (ignored when dst is array) */
|
||||
|
||||
size_t WidthInBytes; /**< Width of 2D memory copy in bytes */
|
||||
size_t Height; /**< Height of 2D memory copy */
|
||||
} CUDA_MEMCPY2D_v2;
|
||||
typedef CUDA_MEMCPY2D_v2 CUDA_MEMCPY2D;
|
||||
|
||||
typedef struct CUgraphicsResource_st *CUgraphicsResource;
|
||||
|
||||
typedef struct gsr_cuda gsr_cuda;
|
||||
struct gsr_cuda {
|
||||
gsr_overclock overclock;
|
||||
bool do_overclock;
|
||||
|
||||
void *library;
|
||||
CUcontext cu_ctx;
|
||||
|
||||
CUresult (*cuInit)(unsigned int Flags);
|
||||
CUresult (*cuDeviceGetCount)(int *count);
|
||||
CUresult (*cuDeviceGet)(CUdevice *device, int ordinal);
|
||||
CUresult (*cuCtxCreate_v2)(CUcontext *pctx, unsigned int flags, CUdevice dev);
|
||||
CUresult (*cuCtxDestroy_v2)(CUcontext ctx);
|
||||
CUresult (*cuCtxPushCurrent_v2)(CUcontext ctx);
|
||||
CUresult (*cuCtxPopCurrent_v2)(CUcontext *pctx);
|
||||
CUresult (*cuGetErrorString)(CUresult error, const char **pStr);
|
||||
CUresult (*cuMemcpy2D_v2)(const CUDA_MEMCPY2D *pCopy);
|
||||
CUresult (*cuMemcpy2DAsync_v2)(const CUDA_MEMCPY2D *pcopy, CUstream hStream);
|
||||
CUresult (*cuStreamSynchronize)(CUstream hStream);
|
||||
|
||||
CUresult (*cuGraphicsGLRegisterImage)(CUgraphicsResource *pCudaResource, unsigned int image, unsigned int target, unsigned int flags);
|
||||
CUresult (*cuGraphicsEGLRegisterImage)(CUgraphicsResource *pCudaResource, void *image, unsigned int flags);
|
||||
CUresult (*cuGraphicsResourceSetMapFlags)(CUgraphicsResource resource, unsigned int flags);
|
||||
CUresult (*cuGraphicsMapResources)(unsigned int count, CUgraphicsResource *resources, CUstream hStream);
|
||||
CUresult (*cuGraphicsUnmapResources)(unsigned int count, CUgraphicsResource *resources, CUstream hStream);
|
||||
CUresult (*cuGraphicsUnregisterResource)(CUgraphicsResource resource);
|
||||
CUresult (*cuGraphicsSubResourceGetMappedArray)(CUarray *pArray, CUgraphicsResource resource, unsigned int arrayIndex, unsigned int mipLevel);
|
||||
};
|
||||
|
||||
bool gsr_cuda_load(gsr_cuda *self, Display *display, bool overclock);
|
||||
void gsr_cuda_unload(gsr_cuda *self);
|
||||
|
||||
#endif /* GSR_CUDA_H */
|
||||
28
include/cursor.h
Normal file
28
include/cursor.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef GSR_CURSOR_H
|
||||
#define GSR_CURSOR_H
|
||||
|
||||
#include "egl.h"
|
||||
#include "vec2.h"
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
Display *display;
|
||||
int x_fixes_event_base;
|
||||
|
||||
unsigned int texture_id;
|
||||
vec2i size;
|
||||
vec2i hotspot;
|
||||
vec2i position;
|
||||
|
||||
bool cursor_image_set;
|
||||
bool visible;
|
||||
} gsr_cursor;
|
||||
|
||||
int gsr_cursor_init(gsr_cursor *self, gsr_egl *egl, Display *display);
|
||||
void gsr_cursor_deinit(gsr_cursor *self);
|
||||
|
||||
/* Returns true if the cursor image has updated or if the cursor has moved */
|
||||
bool gsr_cursor_on_event(gsr_cursor *self, XEvent *xev);
|
||||
void gsr_cursor_tick(gsr_cursor *self, Window relative_to);
|
||||
|
||||
#endif /* GSR_CURSOR_H */
|
||||
74
include/damage.h
Normal file
74
include/damage.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef GSR_DAMAGE_H
|
||||
#define GSR_DAMAGE_H
|
||||
|
||||
#include "cursor.h"
|
||||
#include "utils.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct _XDisplay Display;
|
||||
typedef union _XEvent XEvent;
|
||||
|
||||
#define GSR_DAMAGE_MAX_MONITORS 32
|
||||
#define GSR_DAMAGE_MAX_TRACKED_TARGETS 12
|
||||
|
||||
typedef struct {
|
||||
int64_t window_id;
|
||||
vec2i window_pos;
|
||||
vec2i window_size;
|
||||
uint64_t damage;
|
||||
int refcount;
|
||||
} gsr_damage_window;
|
||||
|
||||
typedef struct {
|
||||
char *monitor_name;
|
||||
gsr_monitor *monitor;
|
||||
int refcount;
|
||||
} gsr_damage_monitor;
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
Display *display;
|
||||
bool track_cursor;
|
||||
|
||||
int damage_event;
|
||||
int damage_error;
|
||||
bool damaged;
|
||||
|
||||
uint64_t monitor_damage;
|
||||
|
||||
int randr_event;
|
||||
int randr_error;
|
||||
|
||||
gsr_cursor *cursor;
|
||||
gsr_monitor monitors[GSR_DAMAGE_MAX_MONITORS];
|
||||
int num_monitors;
|
||||
|
||||
gsr_damage_window windows_tracked[GSR_DAMAGE_MAX_TRACKED_TARGETS];
|
||||
int num_windows_tracked;
|
||||
|
||||
gsr_damage_monitor monitors_tracked[GSR_DAMAGE_MAX_TRACKED_TARGETS];
|
||||
int num_monitors_tracked;
|
||||
|
||||
int all_monitors_tracked_refcount;
|
||||
vec2i cursor_pos;
|
||||
} gsr_damage;
|
||||
|
||||
bool gsr_damage_init(gsr_damage *self, gsr_egl *egl, gsr_cursor *cursor, bool track_cursor);
|
||||
void gsr_damage_deinit(gsr_damage *self);
|
||||
|
||||
/* This is reference counted */
|
||||
bool gsr_damage_start_tracking_window(gsr_damage *self, int64_t window);
|
||||
void gsr_damage_stop_tracking_window(gsr_damage *self, int64_t window);
|
||||
|
||||
/* This is reference counted. If |monitor_name| is NULL then all monitors are tracked */
|
||||
bool gsr_damage_start_tracking_monitor(gsr_damage *self, const char *monitor_name);
|
||||
void gsr_damage_stop_tracking_monitor(gsr_damage *self, const char *monitor_name);
|
||||
|
||||
void gsr_damage_on_event(gsr_damage *self, XEvent *xev);
|
||||
void gsr_damage_tick(gsr_damage *self);
|
||||
/* Also returns true if damage tracking is not available */
|
||||
bool gsr_damage_is_damaged(gsr_damage *self);
|
||||
void gsr_damage_clear(gsr_damage *self);
|
||||
|
||||
#endif /* GSR_DAMAGE_H */
|
||||
49
include/dbus.h
Normal file
49
include/dbus.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef GSR_DBUS_H
|
||||
#define GSR_DBUS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#define DBUS_RANDOM_STR_SIZE 16
|
||||
|
||||
typedef enum {
|
||||
GSR_PORTAL_CAPTURE_TYPE_MONITOR = 1 << 0,
|
||||
GSR_PORTAL_CAPTURE_TYPE_WINDOW = 1 << 1,
|
||||
GSR_PORTAL_CAPTURE_TYPE_VIRTUAL = 1 << 2,
|
||||
GSR_PORTAL_CAPTURE_TYPE_ALL = GSR_PORTAL_CAPTURE_TYPE_MONITOR | GSR_PORTAL_CAPTURE_TYPE_WINDOW | GSR_PORTAL_CAPTURE_TYPE_VIRTUAL
|
||||
} gsr_portal_capture_type;
|
||||
|
||||
typedef enum {
|
||||
GSR_PORTAL_CURSOR_MODE_HIDDEN = 1 << 0,
|
||||
GSR_PORTAL_CURSOR_MODE_EMBEDDED = 1 << 1,
|
||||
GSR_PORTAL_CURSOR_MODE_METADATA = 1 << 2
|
||||
} gsr_portal_cursor_mode;
|
||||
|
||||
typedef struct {
|
||||
DBusConnection *con;
|
||||
DBusError err;
|
||||
char random_str[DBUS_RANDOM_STR_SIZE + 1];
|
||||
unsigned int handle_counter;
|
||||
bool desktop_portal_rule_added;
|
||||
uint32_t screencast_version;
|
||||
char *screencast_restore_token;
|
||||
} gsr_dbus;
|
||||
|
||||
/* Blocking. TODO: Make non-blocking */
|
||||
bool gsr_dbus_init(gsr_dbus *self, const char *screencast_restore_token);
|
||||
void gsr_dbus_deinit(gsr_dbus *self);
|
||||
|
||||
/* The follow functions should be called in order to setup ScreenCast properly */
|
||||
/* These functions that return an int return the response status code */
|
||||
int gsr_dbus_screencast_create_session(gsr_dbus *self, char **session_handle);
|
||||
/*
|
||||
|capture_type| is a bitmask of gsr_portal_capture_type values. gsr_portal_capture_type values that are not supported by the desktop portal will be ignored.
|
||||
|gsr_portal_cursor_mode| is a bitmask of gsr_portal_cursor_mode values. gsr_portal_cursor_mode values that are not supported will be ignored.
|
||||
*/
|
||||
int gsr_dbus_screencast_select_sources(gsr_dbus *self, const char *session_handle, uint32_t capture_type, uint32_t cursor_mode);
|
||||
int gsr_dbus_screencast_start(gsr_dbus *self, const char *session_handle, uint32_t *pipewire_node);
|
||||
bool gsr_dbus_screencast_open_pipewire_remote(gsr_dbus *self, const char *session_handle, int *pipewire_fd);
|
||||
const char* gsr_dbus_screencast_get_restore_token(gsr_dbus *self);
|
||||
|
||||
#endif /* GSR_DBUS_H */
|
||||
112
include/defs.h
Normal file
112
include/defs.h
Normal file
@ -0,0 +1,112 @@
|
||||
#ifndef GSR_DEFS_H
|
||||
#define GSR_DEFS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define GSR_VIDEO_CODEC_AUTO -1
|
||||
#define GSR_BITRATE_MODE_AUTO -1
|
||||
|
||||
typedef enum {
|
||||
GSR_GPU_VENDOR_AMD,
|
||||
GSR_GPU_VENDOR_INTEL,
|
||||
GSR_GPU_VENDOR_NVIDIA,
|
||||
GSR_GPU_VENDOR_BROADCOM,
|
||||
} gsr_gpu_vendor;
|
||||
|
||||
typedef struct {
|
||||
gsr_gpu_vendor vendor;
|
||||
int gpu_version; /* 0 if unknown */
|
||||
bool is_steam_deck;
|
||||
} gsr_gpu_info;
|
||||
|
||||
typedef enum {
|
||||
GSR_MONITOR_ROT_0,
|
||||
GSR_MONITOR_ROT_90,
|
||||
GSR_MONITOR_ROT_180,
|
||||
GSR_MONITOR_ROT_270,
|
||||
} gsr_monitor_rotation;
|
||||
|
||||
typedef enum {
|
||||
GSR_CONNECTION_X11,
|
||||
GSR_CONNECTION_WAYLAND,
|
||||
GSR_CONNECTION_DRM,
|
||||
} gsr_connection_type;
|
||||
|
||||
typedef enum {
|
||||
GSR_VIDEO_QUALITY_MEDIUM,
|
||||
GSR_VIDEO_QUALITY_HIGH,
|
||||
GSR_VIDEO_QUALITY_VERY_HIGH,
|
||||
GSR_VIDEO_QUALITY_ULTRA,
|
||||
} gsr_video_quality;
|
||||
|
||||
typedef enum {
|
||||
GSR_VIDEO_CODEC_H264,
|
||||
GSR_VIDEO_CODEC_HEVC,
|
||||
GSR_VIDEO_CODEC_HEVC_HDR,
|
||||
GSR_VIDEO_CODEC_HEVC_10BIT,
|
||||
GSR_VIDEO_CODEC_AV1,
|
||||
GSR_VIDEO_CODEC_AV1_HDR,
|
||||
GSR_VIDEO_CODEC_AV1_10BIT,
|
||||
GSR_VIDEO_CODEC_VP8,
|
||||
GSR_VIDEO_CODEC_VP9,
|
||||
GSR_VIDEO_CODEC_H264_VULKAN,
|
||||
GSR_VIDEO_CODEC_HEVC_VULKAN,
|
||||
} gsr_video_codec;
|
||||
|
||||
typedef enum {
|
||||
GSR_AUDIO_CODEC_AAC,
|
||||
GSR_AUDIO_CODEC_OPUS,
|
||||
GSR_AUDIO_CODEC_FLAC,
|
||||
} gsr_audio_codec;
|
||||
|
||||
typedef enum {
|
||||
GSR_PIXEL_FORMAT_YUV420,
|
||||
GSR_PIXEL_FORMAT_YUV444,
|
||||
} gsr_pixel_format;
|
||||
|
||||
typedef enum {
|
||||
GSR_FRAMERATE_MODE_CONSTANT,
|
||||
GSR_FRAMERATE_MODE_VARIABLE,
|
||||
GSR_FRAMERATE_MODE_CONTENT,
|
||||
} gsr_framerate_mode;
|
||||
|
||||
typedef enum {
|
||||
GSR_BITRATE_MODE_QP,
|
||||
GSR_BITRATE_MODE_VBR,
|
||||
GSR_BITRATE_MODE_CBR,
|
||||
} gsr_bitrate_mode;
|
||||
|
||||
typedef enum {
|
||||
GSR_TUNE_PERFORMANCE,
|
||||
GSR_TUNE_QUALITY,
|
||||
} gsr_tune;
|
||||
|
||||
typedef enum {
|
||||
GSR_VIDEO_ENCODER_HW_GPU,
|
||||
GSR_VIDEO_ENCODER_HW_CPU,
|
||||
} gsr_video_encoder_hardware;
|
||||
|
||||
typedef enum {
|
||||
GSR_COLOR_RANGE_LIMITED,
|
||||
GSR_COLOR_RANGE_FULL,
|
||||
} gsr_color_range;
|
||||
|
||||
typedef enum {
|
||||
GSR_COLOR_DEPTH_8_BITS,
|
||||
GSR_COLOR_DEPTH_10_BITS,
|
||||
} gsr_color_depth;
|
||||
|
||||
typedef enum {
|
||||
GSR_REPLAY_STORAGE_RAM,
|
||||
GSR_REPLAY_STORAGE_DISK,
|
||||
} gsr_replay_storage;
|
||||
|
||||
bool video_codec_is_hdr(gsr_video_codec video_codec);
|
||||
gsr_video_codec hdr_video_codec_to_sdr_video_codec(gsr_video_codec video_codec);
|
||||
gsr_color_depth video_codec_to_bit_depth(gsr_video_codec video_codec);
|
||||
const char* video_codec_to_string(gsr_video_codec video_codec);
|
||||
bool video_codec_is_av1(gsr_video_codec video_codec);
|
||||
bool video_codec_is_vulkan(gsr_video_codec video_codec);
|
||||
const char* audio_codec_get_name(gsr_audio_codec audio_codec);
|
||||
|
||||
#endif /* GSR_DEFS_H */
|
||||
321
include/egl.h
Normal file
321
include/egl.h
Normal file
@ -0,0 +1,321 @@
|
||||
#ifndef GSR_EGL_H
|
||||
#define GSR_EGL_H
|
||||
|
||||
/* OpenGL EGL library with a hidden window context (to allow using the opengl functions) */
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "vec2.h"
|
||||
#include "defs.h"
|
||||
|
||||
typedef struct gsr_window gsr_window;
|
||||
|
||||
#ifdef _WIN64
|
||||
typedef signed long long int khronos_intptr_t;
|
||||
typedef unsigned long long int khronos_uintptr_t;
|
||||
typedef signed long long int khronos_ssize_t;
|
||||
typedef unsigned long long int khronos_usize_t;
|
||||
#else
|
||||
typedef signed long int khronos_intptr_t;
|
||||
typedef unsigned long int khronos_uintptr_t;
|
||||
typedef signed long int khronos_ssize_t;
|
||||
typedef unsigned long int khronos_usize_t;
|
||||
#endif
|
||||
|
||||
typedef void* EGLDisplay;
|
||||
typedef void* EGLNativeDisplayType;
|
||||
typedef uintptr_t EGLNativeWindowType;
|
||||
typedef uintptr_t EGLNativePixmapType;
|
||||
typedef void* EGLConfig;
|
||||
typedef void* EGLSurface;
|
||||
typedef void* EGLContext;
|
||||
typedef void* EGLClientBuffer;
|
||||
typedef void* EGLImage;
|
||||
typedef void* EGLImageKHR;
|
||||
typedef void *GLeglImageOES;
|
||||
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
|
||||
typedef struct __GLXFBConfigRec *GLXFBConfig;
|
||||
typedef struct __GLXcontextRec *GLXContext;
|
||||
typedef XID GLXDrawable;
|
||||
typedef void(*__GLXextFuncPtr)(void);
|
||||
|
||||
#define EGL_SUCCESS 0x3000
|
||||
#define EGL_BUFFER_SIZE 0x3020
|
||||
#define EGL_RENDERABLE_TYPE 0x3040
|
||||
#define EGL_OPENGL_API 0x30A2
|
||||
#define EGL_OPENGL_ES_API 0x30A0
|
||||
#define EGL_OPENGL_BIT 0x0008
|
||||
#define EGL_OPENGL_ES_BIT 0x0001
|
||||
#define EGL_OPENGL_ES2_BIT 0x0004
|
||||
#define EGL_OPENGL_ES3_BIT 0x00000040
|
||||
#define EGL_NONE 0x3038
|
||||
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
||||
#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0
|
||||
#define EGL_BACK_BUFFER 0x3084
|
||||
#define EGL_GL_TEXTURE_2D 0x30B1
|
||||
#define EGL_TRUE 1
|
||||
#define EGL_IMAGE_PRESERVED_KHR 0x30D2
|
||||
#define EGL_NATIVE_PIXMAP_KHR 0x30B0
|
||||
#define EGL_LINUX_DRM_FOURCC_EXT 0x3271
|
||||
#define EGL_WIDTH 0x3057
|
||||
#define EGL_HEIGHT 0x3056
|
||||
#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
|
||||
#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
|
||||
#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
|
||||
#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
|
||||
#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
|
||||
#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
|
||||
#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
|
||||
#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
|
||||
#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
|
||||
#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
|
||||
#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
|
||||
#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
|
||||
#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
|
||||
#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
|
||||
#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
|
||||
#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
|
||||
#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
|
||||
#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
|
||||
#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
|
||||
#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
|
||||
#define EGL_LINUX_DMA_BUF_EXT 0x3270
|
||||
#define EGL_RED_SIZE 0x3024
|
||||
#define EGL_ALPHA_SIZE 0x3021
|
||||
#define EGL_BLUE_SIZE 0x3022
|
||||
#define EGL_GREEN_SIZE 0x3023
|
||||
#define EGL_DEVICE_EXT 0x322C
|
||||
#define EGL_DRM_DEVICE_FILE_EXT 0x3233
|
||||
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_FALSE 0
|
||||
#define GL_TRUE 1
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
|
||||
#define GL_RED 0x1903
|
||||
#define GL_GREEN 0x1904
|
||||
#define GL_BLUE 0x1905
|
||||
#define GL_ALPHA 0x1906
|
||||
#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
|
||||
#define GL_RG 0x8227
|
||||
#define GL_RGB 0x1907
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_RGB8 0x8051
|
||||
#define GL_RGBA8 0x8058
|
||||
#define GL_RGBA16 0x805B
|
||||
#define GL_R8 0x8229
|
||||
#define GL_RG8 0x822B
|
||||
#define GL_R16 0x822A
|
||||
#define GL_RG16 0x822C
|
||||
#define GL_RGB16 0x8054
|
||||
#define GL_RGBA32F 0x8814
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_FRAMEBUFFER 0x8D40
|
||||
#define GL_COLOR_ATTACHMENT0 0x8CE0
|
||||
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
|
||||
#define GL_DYNAMIC_DRAW 0x88E8
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_BLEND 0x0BE2
|
||||
#define GL_SRC_ALPHA 0x0302
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
||||
#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
#define GL_PACK_ALIGNMENT 0x0D05
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_TEXTURE1 0x84C1
|
||||
#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
|
||||
#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
|
||||
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
|
||||
#define GL_MAP_WRITE_BIT 0x0002
|
||||
|
||||
#define GL_VENDOR 0x1F00
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
|
||||
typedef unsigned int (*FUNC_eglExportDMABUFImageQueryMESA)(EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, uint64_t *modifiers);
|
||||
typedef unsigned int (*FUNC_eglExportDMABUFImageMESA)(EGLDisplay dpy, EGLImageKHR image, int *fds, int32_t *strides, int32_t *offsets);
|
||||
typedef void (*FUNC_glEGLImageTargetTexture2DOES)(unsigned int target, GLeglImageOES image);
|
||||
typedef GLXContext (*FUNC_glXCreateContextAttribsARB)(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
|
||||
typedef void (*FUNC_glXSwapIntervalEXT)(Display * dpy, GLXDrawable drawable, int interval);
|
||||
typedef int (*FUNC_glXSwapIntervalMESA)(unsigned int interval);
|
||||
typedef int (*FUNC_glXSwapIntervalSGI)(int interval);
|
||||
typedef void (*GLDEBUGPROC)(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char *message, const void *userParam);
|
||||
typedef int (*FUNC_eglQueryDisplayAttribEXT)(EGLDisplay dpy, int32_t attribute, intptr_t *value);
|
||||
typedef const char* (*FUNC_eglQueryDeviceStringEXT)(void *device, int32_t name);
|
||||
typedef int (*FUNC_eglQueryDmaBufModifiersEXT)(EGLDisplay dpy, int32_t format, int32_t max_modifiers, uint64_t *modifiers, int *external_only, int32_t *num_modifiers);
|
||||
typedef void (*FUNC_glCreateMemoryObjectsEXT)(int n, unsigned int *memoryObjects);
|
||||
typedef void (*FUNC_glImportMemoryFdEXT)(unsigned int memory, uint64_t size, unsigned int handleType, int fd);
|
||||
typedef unsigned char (*FUNC_glIsMemoryObjectEXT)(unsigned int memoryObject);
|
||||
typedef void (*FUNC_glTexStorageMem2DEXT)(unsigned int target, int levels, unsigned int internalFormat, int width, int height, unsigned int memory, uint64_t offset);
|
||||
typedef void (*FUNC_glBufferStorageMemEXT)(unsigned int target, ssize_t size, unsigned int memory, uint64_t offset);
|
||||
typedef void (*FUNC_glNamedBufferStorageMemEXT)(unsigned int buffer, ssize_t size, unsigned int memory, uint64_t offset);
|
||||
typedef void (*FUNC_glMemoryObjectParameterivEXT)(unsigned int memoryObject, unsigned int pname, const int *params);
|
||||
|
||||
typedef enum {
|
||||
GSR_GL_CONTEXT_TYPE_EGL,
|
||||
GSR_GL_CONTEXT_TYPE_GLX
|
||||
} gsr_gl_context_type;
|
||||
|
||||
typedef struct gsr_egl gsr_egl;
|
||||
struct gsr_egl {
|
||||
void *egl_library;
|
||||
void *glx_library;
|
||||
void *gl_library;
|
||||
|
||||
gsr_gl_context_type context_type;
|
||||
gsr_window *window;
|
||||
|
||||
EGLDisplay egl_display;
|
||||
EGLSurface egl_surface;
|
||||
EGLContext egl_context;
|
||||
const char *dri_card_path;
|
||||
|
||||
void *glx_context;
|
||||
void *glx_fb_config;
|
||||
|
||||
gsr_gpu_info gpu_info;
|
||||
|
||||
char card_path[128];
|
||||
|
||||
int32_t (*eglGetError)(void);
|
||||
EGLDisplay (*eglGetDisplay)(EGLNativeDisplayType display_id);
|
||||
unsigned int (*eglInitialize)(EGLDisplay dpy, int32_t *major, int32_t *minor);
|
||||
unsigned int (*eglTerminate)(EGLDisplay dpy);
|
||||
unsigned int (*eglChooseConfig)(EGLDisplay dpy, const int32_t *attrib_list, EGLConfig *configs, int32_t config_size, int32_t *num_config);
|
||||
EGLSurface (*eglCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const int32_t *attrib_list);
|
||||
EGLContext (*eglCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const int32_t *attrib_list);
|
||||
unsigned int (*eglMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
EGLImage (*eglCreateImage)(EGLDisplay dpy, EGLContext ctx, unsigned int target, EGLClientBuffer buffer, const intptr_t *attrib_list);
|
||||
unsigned int (*eglDestroyContext)(EGLDisplay dpy, EGLContext ctx);
|
||||
unsigned int (*eglDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||
unsigned int (*eglDestroyImage)(EGLDisplay dpy, EGLImage image);
|
||||
unsigned int (*eglSwapInterval)(EGLDisplay dpy, int32_t interval);
|
||||
unsigned int (*eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
||||
unsigned int (*eglBindAPI)(unsigned int api);
|
||||
__eglMustCastToProperFunctionPointerType (*eglGetProcAddress)(const char *procname);
|
||||
|
||||
FUNC_eglExportDMABUFImageQueryMESA eglExportDMABUFImageQueryMESA;
|
||||
FUNC_eglExportDMABUFImageMESA eglExportDMABUFImageMESA;
|
||||
FUNC_glEGLImageTargetTexture2DOES glEGLImageTargetTexture2DOES;
|
||||
FUNC_eglQueryDisplayAttribEXT eglQueryDisplayAttribEXT;
|
||||
FUNC_eglQueryDeviceStringEXT eglQueryDeviceStringEXT;
|
||||
FUNC_eglQueryDmaBufModifiersEXT eglQueryDmaBufModifiersEXT;
|
||||
FUNC_glCreateMemoryObjectsEXT glCreateMemoryObjectsEXT;
|
||||
FUNC_glImportMemoryFdEXT glImportMemoryFdEXT;
|
||||
FUNC_glIsMemoryObjectEXT glIsMemoryObjectEXT;
|
||||
FUNC_glTexStorageMem2DEXT glTexStorageMem2DEXT;
|
||||
FUNC_glBufferStorageMemEXT glBufferStorageMemEXT;
|
||||
FUNC_glNamedBufferStorageMemEXT glNamedBufferStorageMemEXT;
|
||||
FUNC_glMemoryObjectParameterivEXT glMemoryObjectParameterivEXT;
|
||||
|
||||
__GLXextFuncPtr (*glXGetProcAddress)(const unsigned char *procName);
|
||||
GLXFBConfig* (*glXChooseFBConfig)(Display *dpy, int screen, const int *attribList, int *nitems);
|
||||
Bool (*glXMakeContextCurrent)(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
|
||||
// TODO: Remove
|
||||
GLXContext (*glXCreateNewContext)(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct);
|
||||
void (*glXDestroyContext)(Display *dpy, GLXContext ctx);
|
||||
void (*glXSwapBuffers)(Display *dpy, GLXDrawable drawable);
|
||||
FUNC_glXCreateContextAttribsARB glXCreateContextAttribsARB;
|
||||
|
||||
/* Optional */
|
||||
FUNC_glXSwapIntervalEXT glXSwapIntervalEXT;
|
||||
FUNC_glXSwapIntervalMESA glXSwapIntervalMESA;
|
||||
FUNC_glXSwapIntervalSGI glXSwapIntervalSGI;
|
||||
|
||||
unsigned int (*glGetError)(void);
|
||||
const unsigned char* (*glGetString)(unsigned int name);
|
||||
void (*glFlush)(void);
|
||||
void (*glFinish)(void);
|
||||
void (*glClear)(unsigned int mask);
|
||||
void (*glClearColor)(float red, float green, float blue, float alpha);
|
||||
void (*glGenTextures)(int n, unsigned int *textures);
|
||||
void (*glDeleteTextures)(int n, const unsigned int *texture);
|
||||
void (*glActiveTexture)(unsigned int texture);
|
||||
void (*glBindTexture)(unsigned int target, unsigned int texture);
|
||||
void (*glBindImageTexture)(unsigned int unit, unsigned int texture, int level, unsigned char layered, int layer, unsigned int access, unsigned int format);
|
||||
void (*glTexParameteri)(unsigned int target, unsigned int pname, int param);
|
||||
void (*glTexParameteriv)(unsigned int target, unsigned int pname, const int *params);
|
||||
void (*glTexParameterfv)(unsigned int target, unsigned int pname, const float *params);
|
||||
void (*glTexImage2D)(unsigned int target, int level, int internalFormat, int width, int height, int border, unsigned int format, unsigned int type, const void *pixels);
|
||||
void (*glTexSubImage2D)(unsigned int target, int level, int xoffset, int yoffset, int width, int height, unsigned format, unsigned type, const void *pixels);
|
||||
void (*glTexStorage2D)(unsigned int target, int levels, unsigned int internalformat, int width, int height);
|
||||
void (*glGetTexImage)(unsigned int target, int level, unsigned int format, unsigned int type, void *pixels);
|
||||
void (*glGenFramebuffers)(int n, unsigned int *framebuffers);
|
||||
void (*glBindFramebuffer)(unsigned int target, unsigned int framebuffer);
|
||||
void (*glDeleteFramebuffers)(int n, const unsigned int *framebuffers);
|
||||
/* TODO: Note: this is only available since OpenGL ES 3.1 */
|
||||
void (*glMemoryBarrier)(unsigned int barriers);
|
||||
void (*glViewport)(int x, int y, int width, int height);
|
||||
void (*glFramebufferTexture2D)(unsigned int target, unsigned int attachment, unsigned int textarget, unsigned int texture, int level);
|
||||
void (*glDrawBuffers)(int n, const unsigned int *bufs);
|
||||
unsigned int (*glCheckFramebufferStatus)(unsigned int target);
|
||||
void (*glBindBuffer)(unsigned int target, unsigned int buffer);
|
||||
void (*glGenBuffers)(int n, unsigned int *buffers);
|
||||
void (*glBufferData)(unsigned int target, khronos_ssize_t size, const void *data, unsigned int usage);
|
||||
void (*glBufferSubData)(unsigned int target, khronos_intptr_t offset, khronos_ssize_t size, const void *data);
|
||||
void (*glDeleteBuffers)(int n, const unsigned int *buffers);
|
||||
void (*glGenVertexArrays)(int n, unsigned int *arrays);
|
||||
void (*glBindVertexArray)(unsigned int array);
|
||||
void (*glDeleteVertexArrays)(int n, const unsigned int *arrays);
|
||||
unsigned int (*glCreateProgram)(void);
|
||||
unsigned int (*glCreateShader)(unsigned int type);
|
||||
void (*glAttachShader)(unsigned int program, unsigned int shader);
|
||||
void (*glBindAttribLocation)(unsigned int program, unsigned int index, const char *name);
|
||||
void (*glCompileShader)(unsigned int shader);
|
||||
void (*glLinkProgram)(unsigned int program);
|
||||
void (*glShaderSource)(unsigned int shader, int count, const char *const*string, const int *length);
|
||||
void (*glUseProgram)(unsigned int program);
|
||||
void (*glGetProgramInfoLog)(unsigned int program, int bufSize, int *length, char *infoLog);
|
||||
void (*glGetShaderiv)(unsigned int shader, unsigned int pname, int *params);
|
||||
void (*glGetShaderInfoLog)(unsigned int shader, int bufSize, int *length, char *infoLog);
|
||||
void (*glDeleteProgram)(unsigned int program);
|
||||
void (*glDeleteShader)(unsigned int shader);
|
||||
void (*glGetProgramiv)(unsigned int program, unsigned int pname, int *params);
|
||||
void (*glVertexAttribPointer)(unsigned int index, int size, unsigned int type, unsigned char normalized, int stride, const void *pointer);
|
||||
void (*glEnableVertexAttribArray)(unsigned int index);
|
||||
void (*glDrawArrays)(unsigned int mode, int first, int count);
|
||||
void (*glEnable)(unsigned int cap);
|
||||
void (*glDisable)(unsigned int cap);
|
||||
void (*glBlendFunc)(unsigned int sfactor, unsigned int dfactor);
|
||||
void (*glPixelStorei)(unsigned int pname, int param);
|
||||
int (*glGetUniformLocation)(unsigned int program, const char *name);
|
||||
void (*glUniform1f)(int location, float v0);
|
||||
void (*glUniform2f)(int location, float v0, float v1);
|
||||
void (*glUniform1i)(int location, int v0);
|
||||
void (*glUniform2i)(int location, int v0, int v1);
|
||||
void (*glUniformMatrix2fv)(int location, int count, unsigned char transpose, const float *value);
|
||||
void (*glDebugMessageCallback)(GLDEBUGPROC callback, const void *userParam);
|
||||
void (*glScissor)(int x, int y, int width, int height);
|
||||
void (*glCreateBuffers)(int n, unsigned int *buffers);
|
||||
void (*glReadPixels)(int x, int y, int width, int height, unsigned int format, unsigned int type, void *pixels);
|
||||
void* (*glMapBufferRange)(unsigned int target, intptr_t offset, ssize_t length, unsigned int access);
|
||||
unsigned char (*glUnmapBuffer)(unsigned int target);
|
||||
void (*glGetIntegerv)(unsigned int pname, int *params);
|
||||
};
|
||||
|
||||
bool gsr_egl_load(gsr_egl *self, gsr_window *window, bool is_monitor_capture, bool enable_debug);
|
||||
void gsr_egl_unload(gsr_egl *self);
|
||||
|
||||
/* Does opengl swap with egl or glx, depending on which one is active */
|
||||
void gsr_egl_swap_buffers(gsr_egl *self);
|
||||
|
||||
#endif /* GSR_EGL_H */
|
||||
43
include/encoder/encoder.h
Normal file
43
include/encoder/encoder.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef GSR_ENCODER_H
|
||||
#define GSR_ENCODER_H
|
||||
|
||||
#include "../replay_buffer/replay_buffer.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define GSR_MAX_RECORDING_DESTINATIONS 128
|
||||
|
||||
typedef struct AVCodecContext AVCodecContext;
|
||||
typedef struct AVFormatContext AVFormatContext;
|
||||
typedef struct AVStream AVStream;
|
||||
|
||||
typedef struct {
|
||||
size_t id;
|
||||
AVCodecContext *codec_context;
|
||||
AVFormatContext *format_context;
|
||||
AVStream *stream;
|
||||
int64_t start_pts;
|
||||
bool has_received_keyframe;
|
||||
} gsr_encoder_recording_destination;
|
||||
|
||||
typedef struct {
|
||||
gsr_replay_buffer *replay_buffer;
|
||||
pthread_mutex_t file_write_mutex;
|
||||
bool mutex_created;
|
||||
|
||||
gsr_encoder_recording_destination recording_destinations[GSR_MAX_RECORDING_DESTINATIONS];
|
||||
size_t num_recording_destinations;
|
||||
size_t recording_destination_id_counter;
|
||||
} gsr_encoder;
|
||||
|
||||
bool gsr_encoder_init(gsr_encoder *self, gsr_replay_storage replay_storage, size_t replay_buffer_num_packets, double replay_buffer_time, const char *replay_directory);
|
||||
void gsr_encoder_deinit(gsr_encoder *self);
|
||||
|
||||
void gsr_encoder_receive_packets(gsr_encoder *self, AVCodecContext *codec_context, int64_t pts, int stream_index);
|
||||
/* Returns the id to the recording destination, or -1 on error */
|
||||
size_t gsr_encoder_add_recording_destination(gsr_encoder *self, AVCodecContext *codec_context, AVFormatContext *format_context, AVStream *stream, int64_t start_pts);
|
||||
bool gsr_encoder_remove_recording_destination(gsr_encoder *self, size_t id);
|
||||
|
||||
#endif /* GSR_ENCODER_H */
|
||||
16
include/encoder/video/nvenc.h
Normal file
16
include/encoder/video/nvenc.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef GSR_ENCODER_VIDEO_NVENC_H
|
||||
#define GSR_ENCODER_VIDEO_NVENC_H
|
||||
|
||||
#include "video.h"
|
||||
|
||||
typedef struct gsr_egl gsr_egl;
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
bool overclock;
|
||||
gsr_color_depth color_depth;
|
||||
} gsr_video_encoder_nvenc_params;
|
||||
|
||||
gsr_video_encoder* gsr_video_encoder_nvenc_create(const gsr_video_encoder_nvenc_params *params);
|
||||
|
||||
#endif /* GSR_ENCODER_VIDEO_NVENC_H */
|
||||
15
include/encoder/video/software.h
Normal file
15
include/encoder/video/software.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef GSR_ENCODER_VIDEO_SOFTWARE_H
|
||||
#define GSR_ENCODER_VIDEO_SOFTWARE_H
|
||||
|
||||
#include "video.h"
|
||||
|
||||
typedef struct gsr_egl gsr_egl;
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
gsr_color_depth color_depth;
|
||||
} gsr_video_encoder_software_params;
|
||||
|
||||
gsr_video_encoder* gsr_video_encoder_software_create(const gsr_video_encoder_software_params *params);
|
||||
|
||||
#endif /* GSR_ENCODER_VIDEO_SOFTWARE_H */
|
||||
15
include/encoder/video/vaapi.h
Normal file
15
include/encoder/video/vaapi.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef GSR_ENCODER_VIDEO_VAAPI_H
|
||||
#define GSR_ENCODER_VIDEO_VAAPI_H
|
||||
|
||||
#include "video.h"
|
||||
|
||||
typedef struct gsr_egl gsr_egl;
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
gsr_color_depth color_depth;
|
||||
} gsr_video_encoder_vaapi_params;
|
||||
|
||||
gsr_video_encoder* gsr_video_encoder_vaapi_create(const gsr_video_encoder_vaapi_params *params);
|
||||
|
||||
#endif /* GSR_ENCODER_VIDEO_VAAPI_H */
|
||||
30
include/encoder/video/video.h
Normal file
30
include/encoder/video/video.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef GSR_ENCODER_VIDEO_H
|
||||
#define GSR_ENCODER_VIDEO_H
|
||||
|
||||
#include "../../color_conversion.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define GSR_MAX_RECORDING_DESTINATIONS 128
|
||||
|
||||
typedef struct gsr_video_encoder gsr_video_encoder;
|
||||
typedef struct AVCodecContext AVCodecContext;
|
||||
typedef struct AVFrame AVFrame;
|
||||
|
||||
struct gsr_video_encoder {
|
||||
bool (*start)(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame);
|
||||
void (*destroy)(gsr_video_encoder *encoder, AVCodecContext *video_codec_context);
|
||||
void (*copy_textures_to_frame)(gsr_video_encoder *encoder, AVFrame *frame, gsr_color_conversion *color_conversion); /* Can be NULL */
|
||||
/* |textures| should be able to fit 2 elements */
|
||||
void (*get_textures)(gsr_video_encoder *encoder, unsigned int *textures, vec2i *texture_sizes, int *num_textures, gsr_destination_color *destination_color);
|
||||
|
||||
void *priv;
|
||||
bool started;
|
||||
};
|
||||
|
||||
/* Set |replay_buffer_time_seconds| and |fps| to 0 to disable replay buffer */
|
||||
bool gsr_video_encoder_start(gsr_video_encoder *encoder, AVCodecContext *video_codec_context, AVFrame *frame);
|
||||
void gsr_video_encoder_destroy(gsr_video_encoder *encoder, AVCodecContext *video_codec_context);
|
||||
void gsr_video_encoder_copy_textures_to_frame(gsr_video_encoder *encoder, AVFrame *frame, gsr_color_conversion *color_conversion);
|
||||
void gsr_video_encoder_get_textures(gsr_video_encoder *encoder, unsigned int *textures, vec2i *texture_sizes, int *num_textures, gsr_destination_color *destination_color);
|
||||
|
||||
#endif /* GSR_ENCODER_VIDEO_H */
|
||||
15
include/encoder/video/vulkan.h
Normal file
15
include/encoder/video/vulkan.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef GSR_ENCODER_VIDEO_VULKAN_H
|
||||
#define GSR_ENCODER_VIDEO_VULKAN_H
|
||||
|
||||
#include "video.h"
|
||||
|
||||
typedef struct gsr_egl gsr_egl;
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
gsr_color_depth color_depth;
|
||||
} gsr_video_encoder_vulkan_params;
|
||||
|
||||
gsr_video_encoder* gsr_video_encoder_vulkan_create(const gsr_video_encoder_vulkan_params *params);
|
||||
|
||||
#endif /* GSR_ENCODER_VIDEO_VULKAN_H */
|
||||
26
include/image_writer.h
Normal file
26
include/image_writer.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef GSR_IMAGE_WRITER_H
|
||||
#define GSR_IMAGE_WRITER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct gsr_egl gsr_egl;
|
||||
|
||||
typedef enum {
|
||||
GSR_IMAGE_FORMAT_JPEG,
|
||||
GSR_IMAGE_FORMAT_PNG
|
||||
} gsr_image_format;
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
int width;
|
||||
int height;
|
||||
unsigned int texture;
|
||||
} gsr_image_writer;
|
||||
|
||||
bool gsr_image_writer_init_opengl(gsr_image_writer *self, gsr_egl *egl, int width, int height);
|
||||
void gsr_image_writer_deinit(gsr_image_writer *self);
|
||||
|
||||
/* Quality is between 1 and 100 where 100 is the max quality. Quality doesn't apply to lossless formats */
|
||||
bool gsr_image_writer_write_to_file(gsr_image_writer *self, const char *filepath, gsr_image_format image_format, int quality);
|
||||
|
||||
#endif /* GSR_IMAGE_WRITER_H */
|
||||
17
include/library_loader.h
Normal file
17
include/library_loader.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef GSR_LIBRARY_LOADER_H
|
||||
#define GSR_LIBRARY_LOADER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
void **func;
|
||||
const char *name;
|
||||
} dlsym_assign;
|
||||
|
||||
void* dlsym_print_fail(void *handle, const char *name, bool required);
|
||||
/* |dlsyms| should be null terminated */
|
||||
bool dlsym_load_list(void *handle, const dlsym_assign *dlsyms);
|
||||
/* |dlsyms| should be null terminated */
|
||||
void dlsym_load_list_optional(void *handle, const dlsym_assign *dlsyms);
|
||||
|
||||
#endif /* GSR_LIBRARY_LOADER_H */
|
||||
17
include/overclock.h
Normal file
17
include/overclock.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef GSR_OVERCLOCK_H
|
||||
#define GSR_OVERCLOCK_H
|
||||
|
||||
#include "xnvctrl.h"
|
||||
|
||||
typedef struct {
|
||||
gsr_xnvctrl xnvctrl;
|
||||
int num_performance_levels;
|
||||
} gsr_overclock;
|
||||
|
||||
bool gsr_overclock_load(gsr_overclock *self, Display *display);
|
||||
void gsr_overclock_unload(gsr_overclock *self);
|
||||
|
||||
bool gsr_overclock_start(gsr_overclock *self);
|
||||
void gsr_overclock_stop(gsr_overclock *self);
|
||||
|
||||
#endif /* GSR_OVERCLOCK_H */
|
||||
163
include/pipewire_audio.h
Normal file
163
include/pipewire_audio.h
Normal file
@ -0,0 +1,163 @@
|
||||
#ifndef GSR_PIPEWIRE_AUDIO_H
|
||||
#define GSR_PIPEWIRE_AUDIO_H
|
||||
|
||||
#include <pipewire/thread-loop.h>
|
||||
#include <pipewire/context.h>
|
||||
#include <pipewire/core.h>
|
||||
#include <spa/utils/hook.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum {
|
||||
GSR_PIPEWIRE_AUDIO_NODE_TYPE_STREAM_OUTPUT, /* Application audio */
|
||||
GSR_PIPEWIRE_AUDIO_NODE_TYPE_STREAM_INPUT, /* Audio recording input */
|
||||
GSR_PIPEWIRE_AUDIO_NODE_TYPE_SINK_OR_SOURCE /* Audio output or input device or combined (virtual) sink */
|
||||
} gsr_pipewire_audio_node_type;
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
char *name;
|
||||
gsr_pipewire_audio_node_type type;
|
||||
} gsr_pipewire_audio_node;
|
||||
|
||||
typedef enum {
|
||||
GSR_PIPEWIRE_AUDIO_PORT_DIRECTION_INPUT,
|
||||
GSR_PIPEWIRE_AUDIO_PORT_DIRECTION_OUTPUT
|
||||
} gsr_pipewire_audio_port_direction;
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
uint32_t node_id;
|
||||
gsr_pipewire_audio_port_direction direction;
|
||||
char *name;
|
||||
} gsr_pipewire_audio_port;
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
uint32_t output_node_id;
|
||||
uint32_t input_node_id;
|
||||
} gsr_pipewire_audio_link;
|
||||
|
||||
typedef enum {
|
||||
GSR_PIPEWIRE_AUDIO_LINK_INPUT_TYPE_STREAM, /* Application */
|
||||
GSR_PIPEWIRE_AUDIO_LINK_INPUT_TYPE_SINK /* Combined (virtual) sink */
|
||||
} gsr_pipewire_audio_link_input_type;
|
||||
|
||||
typedef enum {
|
||||
GSR_PIPEWIRE_AUDIO_REQUESTED_TYPE_STANDARD,
|
||||
GSR_PIPEWIRE_AUDIO_REQUESTED_TYPE_DEFAULT_OUTPUT,
|
||||
GSR_PIPEWIRE_AUDIO_REQUESTED_TYPE_DEFAULT_INPUT
|
||||
} gsr_pipewire_audio_requested_type;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
gsr_pipewire_audio_requested_type type;
|
||||
} gsr_pipewire_audio_requested_output;
|
||||
|
||||
typedef struct {
|
||||
gsr_pipewire_audio_requested_output *outputs;
|
||||
int num_outputs;
|
||||
char *input_name;
|
||||
bool inverted;
|
||||
gsr_pipewire_audio_node_type output_type;
|
||||
gsr_pipewire_audio_link_input_type input_type;
|
||||
} gsr_pipewire_audio_requested_link;
|
||||
|
||||
typedef struct {
|
||||
struct pw_thread_loop *thread_loop;
|
||||
struct pw_context *context;
|
||||
struct pw_core *core;
|
||||
struct spa_hook core_listener;
|
||||
struct pw_registry *registry;
|
||||
struct spa_hook registry_listener;
|
||||
int server_version_sync;
|
||||
|
||||
struct pw_proxy *metadata_proxy;
|
||||
struct spa_hook metadata_listener;
|
||||
struct spa_hook metadata_proxy_listener;
|
||||
char default_output_device_name[128];
|
||||
char default_input_device_name[128];
|
||||
|
||||
gsr_pipewire_audio_node *stream_nodes;
|
||||
size_t num_stream_nodes;
|
||||
size_t stream_nodes_capacity_items;
|
||||
|
||||
gsr_pipewire_audio_port *ports;
|
||||
size_t num_ports;
|
||||
size_t ports_capacity_items;
|
||||
|
||||
gsr_pipewire_audio_link *links;
|
||||
size_t num_links;
|
||||
size_t links_capacity_items;
|
||||
|
||||
gsr_pipewire_audio_requested_link *requested_links;
|
||||
size_t num_requested_links;
|
||||
size_t requested_links_capacity_items;
|
||||
|
||||
bool running;
|
||||
} gsr_pipewire_audio;
|
||||
|
||||
bool gsr_pipewire_audio_init(gsr_pipewire_audio *self);
|
||||
void gsr_pipewire_audio_deinit(gsr_pipewire_audio *self);
|
||||
|
||||
/*
|
||||
This function links audio source outputs from applications that match the name |app_names| to the input
|
||||
that matches the name |stream_name_input|.
|
||||
If an application or a new application starts outputting audio after this function is called and the app name matches
|
||||
then it will automatically link the audio sources.
|
||||
|app_names| and |stream_name_input| are case-insensitive matches.
|
||||
*/
|
||||
bool gsr_pipewire_audio_add_link_from_apps_to_stream(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *stream_name_input);
|
||||
/*
|
||||
This function links audio source outputs from all applications except the ones that match the name |app_names| to the input
|
||||
that matches the name |stream_name_input|.
|
||||
If an application or a new application starts outputting audio after this function is called and the app name doesn't match
|
||||
then it will automatically link the audio sources.
|
||||
|app_names| and |stream_name_input| are case-insensitive matches.
|
||||
*/
|
||||
bool gsr_pipewire_audio_add_link_from_apps_to_stream_inverted(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *stream_name_input);
|
||||
|
||||
/*
|
||||
This function links audio source outputs from applications that match the name |app_names| to the input
|
||||
that matches the name |sink_name_input|.
|
||||
If an application or a new application starts outputting audio after this function is called and the app name matches
|
||||
then it will automatically link the audio sources.
|
||||
|app_names| and |sink_name_input| are case-insensitive matches.
|
||||
*/
|
||||
bool gsr_pipewire_audio_add_link_from_apps_to_sink(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *sink_name_input);
|
||||
/*
|
||||
This function links audio source outputs from all applications except the ones that match the name |app_names| to the input
|
||||
that matches the name |sink_name_input|.
|
||||
If an application or a new application starts outputting audio after this function is called and the app name doesn't match
|
||||
then it will automatically link the audio sources.
|
||||
|app_names| and |sink_name_input| are case-insensitive matches.
|
||||
*/
|
||||
bool gsr_pipewire_audio_add_link_from_apps_to_sink_inverted(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *sink_name_input);
|
||||
|
||||
/*
|
||||
This function links audio source outputs from devices that match the name |source_names| to the input
|
||||
that matches the name |stream_name_input|.
|
||||
If a device or a new device starts outputting audio after this function is called and the device name matches
|
||||
then it will automatically link the audio sources.
|
||||
|source_names| and |stream_name_input| are case-insensitive matches.
|
||||
|source_names| can include "default_output" or "default_input" to use the default output/input
|
||||
and it will automatically switch when the default output/input is changed in system audio settings.
|
||||
*/
|
||||
bool gsr_pipewire_audio_add_link_from_sources_to_stream(gsr_pipewire_audio *self, const char **source_names, int num_source_names, const char *stream_name_input);
|
||||
|
||||
/*
|
||||
This function links audio source outputs from devices that match the name |source_names| to the input
|
||||
that matches the name |sink_name_input|.
|
||||
If a device or a new device starts outputting audio after this function is called and the device name matches
|
||||
then it will automatically link the audio sources.
|
||||
|source_names| and |sink_name_input| are case-insensitive matches.
|
||||
|source_names| can include "default_output" or "default_input" to use the default output/input
|
||||
and it will automatically switch when the default output/input is changed in system audio settings.
|
||||
*/
|
||||
bool gsr_pipewire_audio_add_link_from_sources_to_sink(gsr_pipewire_audio *self, const char **source_names, int num_source_names, const char *sink_name_input);
|
||||
|
||||
/* Return true to continue */
|
||||
typedef bool (*gsr_pipewire_audio_app_query_callback)(const char *app_name, void *userdata);
|
||||
void gsr_pipewire_audio_for_each_app(gsr_pipewire_audio *self, gsr_pipewire_audio_app_query_callback callback, void *userdata);
|
||||
|
||||
#endif /* GSR_PIPEWIRE_AUDIO_H */
|
||||
132
include/pipewire_video.h
Normal file
132
include/pipewire_video.h
Normal file
@ -0,0 +1,132 @@
|
||||
#ifndef GSR_PIPEWIRE_VIDEO_H
|
||||
#define GSR_PIPEWIRE_VIDEO_H
|
||||
|
||||
#include "defs.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <spa/utils/hook.h>
|
||||
#include <spa/param/video/format.h>
|
||||
|
||||
#define GSR_PIPEWIRE_VIDEO_MAX_MODIFIERS 1024
|
||||
#define GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS 10
|
||||
#define GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES 4
|
||||
|
||||
typedef struct gsr_egl gsr_egl;
|
||||
|
||||
typedef struct {
|
||||
int major;
|
||||
int minor;
|
||||
int micro;
|
||||
} gsr_pipewire_video_data_version;
|
||||
|
||||
typedef struct {
|
||||
uint32_t fps_num;
|
||||
uint32_t fps_den;
|
||||
} gsr_pipewire_video_video_info;
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
uint32_t offset;
|
||||
int32_t stride;
|
||||
} gsr_pipewire_video_dmabuf_data;
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
int width, height;
|
||||
} gsr_pipewire_video_region;
|
||||
|
||||
typedef struct {
|
||||
enum spa_video_format format;
|
||||
size_t modifiers_index;
|
||||
size_t modifiers_size;
|
||||
} gsr_video_format;
|
||||
|
||||
typedef struct {
|
||||
unsigned int texture_id;
|
||||
unsigned int external_texture_id;
|
||||
unsigned int cursor_texture_id;
|
||||
} gsr_texture_map;
|
||||
|
||||
typedef struct {
|
||||
gsr_pipewire_video_region region;
|
||||
gsr_pipewire_video_region cursor_region;
|
||||
gsr_pipewire_video_dmabuf_data dmabuf_data[GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES];
|
||||
int num_dmabuf_data;
|
||||
uint32_t fourcc;
|
||||
uint64_t modifiers;
|
||||
bool using_external_image;
|
||||
gsr_monitor_rotation rotation;
|
||||
int texture_width;
|
||||
int texture_height;
|
||||
} gsr_map_texture_output;
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
int fd;
|
||||
uint32_t node;
|
||||
pthread_mutex_t mutex;
|
||||
bool mutex_initialized;
|
||||
|
||||
struct pw_thread_loop *thread_loop;
|
||||
struct pw_context *context;
|
||||
struct pw_core *core;
|
||||
struct spa_hook core_listener;
|
||||
struct pw_stream *stream;
|
||||
struct spa_hook stream_listener;
|
||||
struct spa_source *reneg;
|
||||
struct spa_video_info format;
|
||||
int server_version_sync;
|
||||
bool negotiated;
|
||||
bool damaged;
|
||||
bool has_modifier;
|
||||
|
||||
struct {
|
||||
bool visible;
|
||||
bool valid;
|
||||
uint8_t *data;
|
||||
int x, y;
|
||||
int hotspot_x, hotspot_y;
|
||||
int width, height;
|
||||
} cursor;
|
||||
|
||||
struct {
|
||||
bool valid;
|
||||
int x, y;
|
||||
uint32_t width, height;
|
||||
} crop;
|
||||
|
||||
gsr_video_format supported_video_formats[GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS];
|
||||
|
||||
gsr_pipewire_video_data_version server_version;
|
||||
gsr_pipewire_video_video_info video_info;
|
||||
gsr_pipewire_video_dmabuf_data dmabuf_data[GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES];
|
||||
size_t dmabuf_num_planes;
|
||||
|
||||
bool no_modifiers_fallback;
|
||||
bool external_texture_fallback;
|
||||
|
||||
uint64_t modifiers[GSR_PIPEWIRE_VIDEO_MAX_MODIFIERS];
|
||||
size_t num_modifiers;
|
||||
|
||||
bool paused;
|
||||
double paused_start_secs;
|
||||
|
||||
gsr_monitor_rotation rotation;
|
||||
} gsr_pipewire_video;
|
||||
|
||||
/*
|
||||
|capture_cursor| only applies to when capturing a window or region.
|
||||
In other cases |pipewire_node|'s setup will determine if the cursor is included.
|
||||
Note that the cursor is not guaranteed to be shown even if set to true, it depends on the wayland compositor.
|
||||
*/
|
||||
bool gsr_pipewire_video_init(gsr_pipewire_video *self, int pipewire_fd, uint32_t pipewire_node, int fps, bool capture_cursor, gsr_egl *egl);
|
||||
void gsr_pipewire_video_deinit(gsr_pipewire_video *self);
|
||||
|
||||
bool gsr_pipewire_video_map_texture(gsr_pipewire_video *self, gsr_texture_map texture_map, gsr_map_texture_output *output);
|
||||
bool gsr_pipewire_video_is_damaged(gsr_pipewire_video *self);
|
||||
void gsr_pipewire_video_clear_damage(gsr_pipewire_video *self);
|
||||
bool gsr_pipewire_video_should_restart(gsr_pipewire_video *self);
|
||||
|
||||
#endif /* GSR_PIPEWIRE_VIDEO_H */
|
||||
38
include/plugins.h
Normal file
38
include/plugins.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef GSR_PLUGINS_H
|
||||
#define GSR_PLUGINS_H
|
||||
|
||||
#include "../plugin/plugin.h"
|
||||
#include <stdbool.h>
|
||||
#include "color_conversion.h"
|
||||
|
||||
#define GSR_MAX_PLUGINS 128
|
||||
|
||||
typedef bool (*gsr_plugin_init_func)(const gsr_plugin_init_params *params, gsr_plugin_init_return *ret);
|
||||
typedef void (*gsr_plugin_deinit_func)(void *userdata);
|
||||
|
||||
typedef struct {
|
||||
gsr_plugin_init_return data;
|
||||
void *lib;
|
||||
gsr_plugin_init_func gsr_plugin_init;
|
||||
gsr_plugin_deinit_func gsr_plugin_deinit;
|
||||
} gsr_plugin;
|
||||
|
||||
typedef struct {
|
||||
gsr_plugin plugins[GSR_MAX_PLUGINS];
|
||||
int num_plugins;
|
||||
|
||||
gsr_plugin_init_params init_params;
|
||||
gsr_egl *egl;
|
||||
|
||||
unsigned int texture;
|
||||
gsr_color_conversion color_conversion;
|
||||
} gsr_plugins;
|
||||
|
||||
bool gsr_plugins_init(gsr_plugins *self, gsr_plugin_init_params init_params, gsr_egl *egl);
|
||||
/* Plugins are unloaded in reverse order */
|
||||
void gsr_plugins_deinit(gsr_plugins *self);
|
||||
|
||||
bool gsr_plugins_load_plugin(gsr_plugins *self, const char *plugin_filepath);
|
||||
void gsr_plugins_draw(gsr_plugins *self);
|
||||
|
||||
#endif /* GSR_PLUGINS_H */
|
||||
54
include/replay_buffer/replay_buffer.h
Normal file
54
include/replay_buffer/replay_buffer.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef GSR_REPLAY_BUFFER_H
|
||||
#define GSR_REPLAY_BUFFER_H
|
||||
|
||||
#include "../defs.h"
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <libavcodec/packet.h>
|
||||
|
||||
typedef struct gsr_replay_buffer gsr_replay_buffer;
|
||||
|
||||
typedef struct {
|
||||
size_t packet_index;
|
||||
size_t file_index;
|
||||
} gsr_replay_buffer_iterator;
|
||||
|
||||
struct gsr_replay_buffer {
|
||||
void (*destroy)(gsr_replay_buffer *self);
|
||||
bool (*append)(gsr_replay_buffer *self, const AVPacket *av_packet, double timestamp);
|
||||
void (*clear)(gsr_replay_buffer *self);
|
||||
AVPacket* (*iterator_get_packet)(gsr_replay_buffer *self, gsr_replay_buffer_iterator iterator);
|
||||
/* The returned data should be free'd with free */
|
||||
uint8_t* (*iterator_get_packet_data)(gsr_replay_buffer *self, gsr_replay_buffer_iterator iterator);
|
||||
/* The clone has to be destroyed before the replay buffer it clones is destroyed */
|
||||
gsr_replay_buffer* (*clone)(gsr_replay_buffer *self);
|
||||
/* Returns {0, 0} if replay buffer is empty */
|
||||
gsr_replay_buffer_iterator (*find_packet_index_by_time_passed)(gsr_replay_buffer *self, int seconds);
|
||||
/* Returns {-1, 0} if not found */
|
||||
gsr_replay_buffer_iterator (*find_keyframe)(gsr_replay_buffer *self, gsr_replay_buffer_iterator start_iterator, int stream_index, bool invert_stream_index);
|
||||
bool (*iterator_next)(gsr_replay_buffer *self, gsr_replay_buffer_iterator *iterator);
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
bool mutex_initialized;
|
||||
gsr_replay_buffer *original_replay_buffer;
|
||||
};
|
||||
|
||||
gsr_replay_buffer* gsr_replay_buffer_create(gsr_replay_storage replay_storage, const char *replay_directory, double replay_buffer_time, size_t replay_buffer_num_packets);
|
||||
void gsr_replay_buffer_destroy(gsr_replay_buffer *self);
|
||||
|
||||
void gsr_replay_buffer_lock(gsr_replay_buffer *self);
|
||||
void gsr_replay_buffer_unlock(gsr_replay_buffer *self);
|
||||
bool gsr_replay_buffer_append(gsr_replay_buffer *self, const AVPacket *av_packet, double timestamp);
|
||||
void gsr_replay_buffer_clear(gsr_replay_buffer *self);
|
||||
AVPacket* gsr_replay_buffer_iterator_get_packet(gsr_replay_buffer *self, gsr_replay_buffer_iterator iterator);
|
||||
/* The returned data should be free'd with free */
|
||||
uint8_t* gsr_replay_buffer_iterator_get_packet_data(gsr_replay_buffer *self, gsr_replay_buffer_iterator iterator);
|
||||
/* The clone has to be destroyed before the replay buffer it clones is destroyed */
|
||||
gsr_replay_buffer* gsr_replay_buffer_clone(gsr_replay_buffer *self);
|
||||
/* Returns {0, 0} if replay buffer is empty */
|
||||
gsr_replay_buffer_iterator gsr_replay_buffer_find_packet_index_by_time_passed(gsr_replay_buffer *self, int seconds);
|
||||
/* Returns {-1, 0} if not found */
|
||||
gsr_replay_buffer_iterator gsr_replay_buffer_find_keyframe(gsr_replay_buffer *self, gsr_replay_buffer_iterator start_iterator, int stream_index, bool invert_stream_index);
|
||||
bool gsr_replay_buffer_iterator_next(gsr_replay_buffer *self, gsr_replay_buffer_iterator *iterator);
|
||||
|
||||
#endif /* GSR_REPLAY_BUFFER_H */
|
||||
44
include/replay_buffer/replay_buffer_disk.h
Normal file
44
include/replay_buffer/replay_buffer_disk.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef GSR_REPLAY_BUFFER_DISK_H
|
||||
#define GSR_REPLAY_BUFFER_DISK_H
|
||||
|
||||
#include "replay_buffer.h"
|
||||
#include <limits.h>
|
||||
|
||||
#define GSR_REPLAY_BUFFER_CAPACITY_NUM_FILES 1024
|
||||
|
||||
typedef struct {
|
||||
AVPacket packet;
|
||||
size_t data_index;
|
||||
double timestamp;
|
||||
} gsr_av_packet_disk;
|
||||
|
||||
typedef struct {
|
||||
size_t id;
|
||||
double start_timestamp;
|
||||
double end_timestamp;
|
||||
int ref_counter;
|
||||
int fd;
|
||||
|
||||
gsr_av_packet_disk *packets;
|
||||
size_t capacity_num_packets;
|
||||
size_t num_packets;
|
||||
} gsr_replay_buffer_file;
|
||||
|
||||
typedef struct {
|
||||
gsr_replay_buffer replay_buffer;
|
||||
double replay_buffer_time;
|
||||
|
||||
size_t storage_counter;
|
||||
size_t storage_num_bytes_written;
|
||||
int storage_fd;
|
||||
gsr_replay_buffer_file *files[GSR_REPLAY_BUFFER_CAPACITY_NUM_FILES]; // GSR_REPLAY_BUFFER_CAPACITY_NUM_FILES * REPLAY_BUFFER_FILE_SIZE_BYTES = 256gb, should be enough for everybody
|
||||
size_t num_files;
|
||||
|
||||
char replay_directory[PATH_MAX];
|
||||
|
||||
bool owns_directory;
|
||||
} gsr_replay_buffer_disk;
|
||||
|
||||
gsr_replay_buffer* gsr_replay_buffer_disk_create(const char *replay_directory, double replay_buffer_time);
|
||||
|
||||
#endif /* GSR_REPLAY_BUFFER_DISK_H */
|
||||
22
include/replay_buffer/replay_buffer_ram.h
Normal file
22
include/replay_buffer/replay_buffer_ram.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef GSR_REPLAY_BUFFER_RAM_H
|
||||
#define GSR_REPLAY_BUFFER_RAM_H
|
||||
|
||||
#include "replay_buffer.h"
|
||||
|
||||
typedef struct {
|
||||
AVPacket packet;
|
||||
int ref_counter;
|
||||
double timestamp;
|
||||
} gsr_av_packet_ram;
|
||||
|
||||
typedef struct {
|
||||
gsr_replay_buffer replay_buffer;
|
||||
gsr_av_packet_ram **packets;
|
||||
size_t capacity_num_packets;
|
||||
size_t num_packets;
|
||||
size_t index;
|
||||
} gsr_replay_buffer_ram;
|
||||
|
||||
gsr_replay_buffer* gsr_replay_buffer_ram_create(size_t replay_buffer_num_packets);
|
||||
|
||||
#endif /* GSR_REPLAY_BUFFER_RAM_H */
|
||||
23
include/shader.h
Normal file
23
include/shader.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef GSR_SHADER_H
|
||||
#define GSR_SHADER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct gsr_egl gsr_egl;
|
||||
|
||||
typedef struct {
|
||||
gsr_egl *egl;
|
||||
unsigned int program_id;
|
||||
} gsr_shader;
|
||||
|
||||
/* |vertex_shader| or |fragment_shader| may be NULL */
|
||||
int gsr_shader_init(gsr_shader *self, gsr_egl *egl, const char *vertex_shader, const char *fragment_shader);
|
||||
void gsr_shader_deinit(gsr_shader *self);
|
||||
|
||||
int gsr_shader_bind_attribute_location(gsr_shader *self, const char *attribute, int location);
|
||||
void gsr_shader_use(gsr_shader *self);
|
||||
void gsr_shader_use_none(gsr_shader *self);
|
||||
|
||||
void gsr_shader_enable_debug_output(bool enable);
|
||||
|
||||
#endif /* GSR_SHADER_H */
|
||||
82
include/sound.hpp
Normal file
82
include/sound.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright (C) 2020 dec05eba
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GPU_SCREEN_RECORDER_H
|
||||
#define GPU_SCREEN_RECORDER_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
typedef struct {
|
||||
void *handle;
|
||||
unsigned int frames;
|
||||
} SoundDevice;
|
||||
|
||||
struct AudioDevice {
|
||||
std::string name;
|
||||
std::string description;
|
||||
};
|
||||
|
||||
struct AudioDevices {
|
||||
std::string default_output;
|
||||
std::string default_input;
|
||||
std::vector<AudioDevice> audio_inputs;
|
||||
};
|
||||
|
||||
enum class AudioInputType {
|
||||
DEVICE,
|
||||
APPLICATION
|
||||
};
|
||||
|
||||
struct AudioInput {
|
||||
std::string name;
|
||||
AudioInputType type = AudioInputType::DEVICE;
|
||||
bool inverted = false;
|
||||
};
|
||||
|
||||
struct MergedAudioInputs {
|
||||
std::string track_name;
|
||||
std::vector<AudioInput> audio_inputs;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
S16,
|
||||
S32,
|
||||
F32
|
||||
} AudioFormat;
|
||||
|
||||
/*
|
||||
Get a sound device by name, returning the device into the |device| parameter.
|
||||
|device_name| can be a device name or "default_output", "default_input" or "" to not connect to any device (used for app audio for example).
|
||||
If the device name is "default_output" or "default_input" then it will automatically switch which
|
||||
device is records from when the default output/input is changed in the system audio settings.
|
||||
Returns 0 on success, or a negative value on failure.
|
||||
*/
|
||||
int sound_device_get_by_name(SoundDevice *device, const char *node_name, const char *device_name, const char *description, unsigned int num_channels, unsigned int period_frame_size, AudioFormat audio_format);
|
||||
|
||||
void sound_device_close(SoundDevice *device);
|
||||
|
||||
/*
|
||||
Returns the next chunk of audio into @buffer.
|
||||
Returns the number of frames read, or a negative value on failure.
|
||||
*/
|
||||
int sound_device_read_next_chunk(SoundDevice *device, void **buffer, double timeout_sec, double *latency_seconds);
|
||||
|
||||
AudioDevices get_pulseaudio_inputs();
|
||||
bool pulseaudio_server_is_pipewire();
|
||||
|
||||
#endif /* GPU_SCREEN_RECORDER_H */
|
||||
65
include/utils.h
Normal file
65
include/utils.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef GSR_UTILS_H
|
||||
#define GSR_UTILS_H
|
||||
|
||||
#include "vec2.h"
|
||||
#include "../include/egl.h"
|
||||
#include "../include/defs.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct AVCodecContext AVCodecContext;
|
||||
typedef struct AVFrame AVFrame;
|
||||
typedef struct gsr_capture_metadata gsr_capture_metadata;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int name_len;
|
||||
vec2i pos; /* This is 0, 0 on wayland. Use |drm_monitor_get_display_server_data| to get the position */
|
||||
vec2i size;
|
||||
uint32_t connector_id; /* Only on x11 and drm */
|
||||
gsr_monitor_rotation rotation; /* Only on x11 and wayland */
|
||||
uint32_t monitor_identifier; /* On x11 this is the crtc id */
|
||||
} gsr_monitor;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int name_len;
|
||||
gsr_monitor *monitor;
|
||||
bool found_monitor;
|
||||
} get_monitor_by_name_userdata;
|
||||
|
||||
double clock_get_monotonic_seconds(void);
|
||||
bool generate_random_characters(char *buffer, int buffer_size, const char *alphabet, size_t alphabet_size);
|
||||
bool generate_random_characters_standard_alphabet(char *buffer, int buffer_size);
|
||||
|
||||
typedef void (*active_monitor_callback)(const gsr_monitor *monitor, void *userdata);
|
||||
void for_each_active_monitor_output_x11_not_cached(Display *display, active_monitor_callback callback, void *userdata);
|
||||
void for_each_active_monitor_output(const gsr_window *window, const char *card_path, gsr_connection_type connection_type, active_monitor_callback callback, void *userdata);
|
||||
bool get_monitor_by_name(const gsr_egl *egl, gsr_connection_type connection_type, const char *name, gsr_monitor *monitor);
|
||||
bool drm_monitor_get_display_server_data(const gsr_window *window, const gsr_monitor *monitor, gsr_monitor_rotation *monitor_rotation, vec2i *monitor_position);
|
||||
|
||||
int get_connector_type_by_name(const char *name);
|
||||
int get_connector_type_id_by_name(const char *name);
|
||||
uint32_t monitor_identifier_from_type_and_count(int monitor_type_index, int monitor_type_count);
|
||||
|
||||
bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info);
|
||||
|
||||
bool try_card_has_valid_plane(const char *card_path);
|
||||
/* |output| should be at least 128 bytes in size */
|
||||
bool gsr_get_valid_card_path(gsr_egl *egl, char *output, bool is_monitor_capture);
|
||||
/* |render_path| should be at least 128 bytes in size */
|
||||
bool gsr_card_path_get_render_path(const char *card_path, char *render_path);
|
||||
|
||||
int create_directory_recursive(char *path);
|
||||
|
||||
/* |img_attr| needs to be at least 44 in size */
|
||||
void setup_dma_buf_attrs(intptr_t *img_attr, uint32_t format, uint32_t width, uint32_t height, const int *fds, const uint32_t *offsets, const uint32_t *pitches, const uint64_t *modifiers, int num_planes, bool use_modifier);
|
||||
|
||||
vec2i scale_keep_aspect_ratio(vec2i from, vec2i to);
|
||||
vec2i gsr_capture_get_target_position(vec2i output_size, gsr_capture_metadata *capture_metadata);
|
||||
|
||||
unsigned int gl_create_texture(gsr_egl *egl, int width, int height, int internal_format, unsigned int format, int filter);
|
||||
|
||||
bool get_nvidia_driver_version(int *major, int *minor);
|
||||
|
||||
#endif /* GSR_UTILS_H */
|
||||
16
include/vec2.h
Normal file
16
include/vec2.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef VEC2_H
|
||||
#define VEC2_H
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
} vec2i;
|
||||
|
||||
typedef struct {
|
||||
float x, y;
|
||||
} vec2f;
|
||||
|
||||
typedef struct {
|
||||
double x, y;
|
||||
} vec2d;
|
||||
|
||||
#endif /* VEC2_H */
|
||||
8
include/window/wayland.h
Normal file
8
include/window/wayland.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef GSR_WINDOW_WAYLAND_H
|
||||
#define GSR_WINDOW_WAYLAND_H
|
||||
|
||||
#include "window.h"
|
||||
|
||||
gsr_window* gsr_window_wayland_create(void);
|
||||
|
||||
#endif /* GSR_WINDOW_WAYLAND_H */
|
||||
37
include/window/window.h
Normal file
37
include/window/window.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef GSR_WINDOW_H
|
||||
#define GSR_WINDOW_H
|
||||
|
||||
#include "../utils.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef union _XEvent XEvent;
|
||||
typedef struct gsr_window gsr_window;
|
||||
|
||||
typedef enum {
|
||||
GSR_DISPLAY_SERVER_X11,
|
||||
GSR_DISPLAY_SERVER_WAYLAND
|
||||
} gsr_display_server;
|
||||
|
||||
struct gsr_window {
|
||||
void (*destroy)(gsr_window *self);
|
||||
/* Returns true if an event is available */
|
||||
bool (*process_event)(gsr_window *self);
|
||||
XEvent* (*get_event_data)(gsr_window *self); /* can be NULL */
|
||||
gsr_display_server (*get_display_server)(void);
|
||||
void* (*get_display)(gsr_window *self);
|
||||
void* (*get_window)(gsr_window *self);
|
||||
void (*for_each_active_monitor_output_cached)(const gsr_window *self, active_monitor_callback callback, void *userdata);
|
||||
void *priv;
|
||||
};
|
||||
|
||||
void gsr_window_destroy(gsr_window *self);
|
||||
|
||||
/* Returns true if an event is available */
|
||||
bool gsr_window_process_event(gsr_window *self);
|
||||
XEvent* gsr_window_get_event_data(gsr_window *self);
|
||||
gsr_display_server gsr_window_get_display_server(const gsr_window *self);
|
||||
void* gsr_window_get_display(gsr_window *self);
|
||||
void* gsr_window_get_window(gsr_window *self);
|
||||
void gsr_window_for_each_active_monitor_output_cached(const gsr_window *self, active_monitor_callback callback, void *userdata);
|
||||
|
||||
#endif /* GSR_WINDOW_H */
|
||||
10
include/window/x11.h
Normal file
10
include/window/x11.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef GSR_WINDOW_X11_H
|
||||
#define GSR_WINDOW_X11_H
|
||||
|
||||
#include "window.h"
|
||||
|
||||
typedef struct _XDisplay Display;
|
||||
|
||||
gsr_window* gsr_window_x11_create(Display *display);
|
||||
|
||||
#endif /* GSR_WINDOW_X11_H */
|
||||
30
include/window_texture.h
Normal file
30
include/window_texture.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef WINDOW_TEXTURE_H
|
||||
#define WINDOW_TEXTURE_H
|
||||
|
||||
#include "egl.h"
|
||||
|
||||
typedef struct {
|
||||
Display *display;
|
||||
Window window;
|
||||
Pixmap pixmap;
|
||||
EGLImage image;
|
||||
unsigned int texture_id;
|
||||
int redirected;
|
||||
gsr_egl *egl;
|
||||
unsigned int window_width;
|
||||
unsigned int window_height;
|
||||
} WindowTexture;
|
||||
|
||||
/* Returns 0 on success */
|
||||
int window_texture_init(WindowTexture *window_texture, Display *display, Window window, gsr_egl *egl);
|
||||
void window_texture_deinit(WindowTexture *self);
|
||||
|
||||
/*
|
||||
This should ONLY be called when the target window is resized.
|
||||
Returns 0 on success.
|
||||
*/
|
||||
int window_texture_on_resize(WindowTexture *self);
|
||||
|
||||
unsigned int window_texture_get_opengl_texture_id(WindowTexture *self);
|
||||
|
||||
#endif /* WINDOW_TEXTURE_H */
|
||||
45
include/xnvctrl.h
Normal file
45
include/xnvctrl.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef GSR_XNVCTRL_H
|
||||
#define GSR_XNVCTRL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define NV_CTRL_GPU_NVCLOCK_OFFSET 409
|
||||
#define NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET 410
|
||||
#define NV_CTRL_GPU_NVCLOCK_OFFSET_ALL_PERFORMANCE_LEVELS 424
|
||||
#define NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET_ALL_PERFORMANCE_LEVELS 425
|
||||
|
||||
#define NV_CTRL_TARGET_TYPE_GPU 1
|
||||
|
||||
#define NV_CTRL_STRING_PERFORMANCE_MODES 29
|
||||
|
||||
typedef struct _XDisplay Display;
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
union {
|
||||
struct {
|
||||
int64_t min;
|
||||
int64_t max;
|
||||
} range;
|
||||
struct {
|
||||
unsigned int ints;
|
||||
} bits;
|
||||
} u;
|
||||
unsigned int permissions;
|
||||
} NVCTRLAttributeValidValuesRec;
|
||||
|
||||
typedef struct {
|
||||
Display *display;
|
||||
void *library;
|
||||
|
||||
int (*XNVCTRLQueryExtension)(Display *dpy, int *event_basep, int *error_basep);
|
||||
int (*XNVCTRLSetTargetAttributeAndGetStatus)(Display *dpy, int target_type, int target_id, unsigned int display_mask, unsigned int attribute, int value);
|
||||
int (*XNVCTRLQueryValidTargetAttributeValues)(Display *dpy, int target_type, int target_id, unsigned int display_mask, unsigned int attribute, NVCTRLAttributeValidValuesRec *values);
|
||||
int (*XNVCTRLQueryTargetStringAttribute)(Display *dpy, int target_type, int target_id, unsigned int display_mask, unsigned int attribute, char **ptr);
|
||||
} gsr_xnvctrl;
|
||||
|
||||
bool gsr_xnvctrl_load(gsr_xnvctrl *self, Display *display);
|
||||
void gsr_xnvctrl_unload(gsr_xnvctrl *self);
|
||||
|
||||
#endif /* GSR_XNVCTRL_H */
|
||||
Reference in New Issue
Block a user