diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/args_parser.h | 106 | ||||
-rw-r--r-- | include/capture/capture.h | 5 | ||||
-rw-r--r-- | include/color_conversion.h | 35 | ||||
-rw-r--r-- | include/dbus.h | 20 | ||||
-rw-r--r-- | include/defs.h | 91 | ||||
-rw-r--r-- | include/egl.h | 20 | ||||
-rw-r--r-- | include/encoder/encoder.h | 43 | ||||
-rw-r--r-- | include/encoder/video/video.h | 7 | ||||
-rw-r--r-- | include/pipewire_audio.h | 31 | ||||
-rw-r--r-- | include/pipewire_video.h | 7 | ||||
-rw-r--r-- | include/replay_buffer/replay_buffer.h | 54 | ||||
-rw-r--r-- | include/replay_buffer/replay_buffer_disk.h | 44 | ||||
-rw-r--r-- | include/replay_buffer/replay_buffer_ram.h | 22 | ||||
-rw-r--r-- | include/shader.h | 4 | ||||
-rw-r--r-- | include/utils.h | 11 |
15 files changed, 434 insertions, 66 deletions
diff --git a/include/args_parser.h b/include/args_parser.h new file mode 100644 index 0000000..e2fa46e --- /dev/null +++ b/include/args_parser.h @@ -0,0 +1,106 @@ +#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 30 + +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_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; + char window[64]; + 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 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 */ diff --git a/include/capture/capture.h b/include/capture/capture.h index 634eee0..c2128c5 100644 --- a/include/capture/capture.h +++ b/include/capture/capture.h @@ -22,12 +22,13 @@ typedef struct { } gsr_capture_metadata; struct gsr_capture { - /* These methods should not be called manually. Call gsr_capture_* instead */ + /* These methods should not be called manually. Call gsr_capture_* instead. |capture_metdata->width| and |capture_metadata->height| 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 */ - int (*capture)(gsr_capture *cap, gsr_capture_metadata *capture_metadata, gsr_color_conversion *color_conversion); + 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) */ + 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 */ diff --git a/include/color_conversion.h b/include/color_conversion.h index 1c067e2..cb074a1 100644 --- a/include/color_conversion.h +++ b/include/color_conversion.h @@ -6,20 +6,11 @@ #include "vec2.h" #include <stdbool.h> -#define GSR_COLOR_CONVERSION_MAX_SHADERS 6 +#define GSR_COLOR_CONVERSION_MAX_COMPUTE_SHADERS 12 +#define GSR_COLOR_CONVERSION_MAX_GRAPHICS_SHADERS 6 #define GSR_COLOR_CONVERSION_MAX_FRAMEBUFFERS 2 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_SOURCE_COLOR_RGB, GSR_SOURCE_COLOR_BGR } gsr_source_color; @@ -39,10 +30,15 @@ typedef enum { typedef struct { int rotation_matrix; + int offset; +} gsr_color_graphics_uniforms; + +typedef struct { + int rotation_matrix; int source_position; int target_position; int scale; -} gsr_color_uniforms; +} gsr_color_compute_uniforms; typedef struct { gsr_egl *egl; @@ -54,12 +50,20 @@ typedef struct { gsr_color_range color_range; bool load_external_image_shader; + bool force_graphics_shader; } gsr_color_conversion_params; typedef struct { gsr_color_conversion_params params; - gsr_color_uniforms uniforms[GSR_COLOR_CONVERSION_MAX_SHADERS]; - gsr_shader shaders[GSR_COLOR_CONVERSION_MAX_SHADERS]; + gsr_color_compute_uniforms compute_uniforms[GSR_COLOR_CONVERSION_MAX_COMPUTE_SHADERS]; + gsr_shader compute_shaders[GSR_COLOR_CONVERSION_MAX_COMPUTE_SHADERS]; + + /* These are only loader if compute shaders (of the same type) fail to load */ + gsr_color_graphics_uniforms graphics_uniforms[GSR_COLOR_CONVERSION_MAX_GRAPHICS_SHADERS]; + gsr_shader graphics_shaders[GSR_COLOR_CONVERSION_MAX_GRAPHICS_SHADERS]; + + bool compute_shaders_failed_to_load; + bool external_compute_shaders_failed_to_load; unsigned int framebuffers[GSR_COLOR_CONVERSION_MAX_FRAMEBUFFERS]; @@ -72,8 +76,9 @@ typedef struct { 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, bool external_texture, gsr_source_color source_color); +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_source_color source_color, bool external_texture, bool alpha_blending); 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); diff --git a/include/dbus.h b/include/dbus.h index 58edf3c..229f7ea 100644 --- a/include/dbus.h +++ b/include/dbus.h @@ -7,16 +7,6 @@ #define DBUS_RANDOM_STR_SIZE 16 -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; - typedef enum { GSR_PORTAL_CAPTURE_TYPE_MONITOR = 1 << 0, GSR_PORTAL_CAPTURE_TYPE_WINDOW = 1 << 1, @@ -30,6 +20,16 @@ typedef enum { 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); diff --git a/include/defs.h b/include/defs.h index 365a6e2..d780005 100644 --- a/include/defs.h +++ b/include/defs.h @@ -3,35 +3,110 @@ #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_BROADCOM, } gsr_gpu_vendor; typedef struct { gsr_gpu_vendor vendor; int gpu_version; /* 0 if unknown */ bool is_steam_deck; - - /* Only currently set for Mesa. 0 if unknown format */ - int driver_major; - int driver_minor; - int driver_patch; } gsr_gpu_info; typedef enum { GSR_MONITOR_ROT_0, GSR_MONITOR_ROT_90, GSR_MONITOR_ROT_180, - GSR_MONITOR_ROT_270 + GSR_MONITOR_ROT_270, } gsr_monitor_rotation; typedef enum { GSR_CONNECTION_X11, GSR_CONNECTION_WAYLAND, - GSR_CONNECTION_DRM + 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 */ diff --git a/include/egl.h b/include/egl.h index 730502f..e11557e 100644 --- a/include/egl.h +++ b/include/egl.h @@ -48,6 +48,8 @@ typedef void(*__GLXextFuncPtr)(void); #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_BACK_BUFFER 0x3084 @@ -141,8 +143,6 @@ typedef void(*__GLXextFuncPtr)(void); #define GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS 0x90EB #define GL_TEXTURE0 0x84C0 #define GL_TEXTURE1 0x84C1 -#define GL_CLAMP_TO_BORDER 0x812D -#define GL_TEXTURE_BORDER_COLOR 0x1004 #define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 #define GL_ALL_BARRIER_BITS 0xFFFFFFFF @@ -169,6 +169,13 @@ typedef void (*GLDEBUGPROC)(unsigned int source, unsigned int type, unsigned int 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, @@ -219,6 +226,13 @@ struct gsr_egl { 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); @@ -251,6 +265,7 @@ struct gsr_egl { void (*glGetTexLevelParameteriv)(unsigned int target, int level, unsigned int pname, int *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); @@ -298,6 +313,7 @@ struct gsr_egl { 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* (*glMapBuffer)(unsigned int target, unsigned int access); unsigned char (*glUnmapBuffer)(unsigned int target); diff --git a/include/encoder/encoder.h b/include/encoder/encoder.h new file mode 100644 index 0000000..7e550f6 --- /dev/null +++ b/include/encoder/encoder.h @@ -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 */ diff --git a/include/encoder/video/video.h b/include/encoder/video/video.h index 49f48bd..7a706b5 100644 --- a/include/encoder/video/video.h +++ b/include/encoder/video/video.h @@ -4,24 +4,27 @@ #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, int *num_textures, gsr_destination_color *destination_color); - void (*destroy)(gsr_video_encoder *encoder, AVCodecContext *video_codec_context); 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, int *num_textures, gsr_destination_color *destination_color); -void gsr_video_encoder_destroy(gsr_video_encoder *encoder, AVCodecContext *video_codec_context); #endif /* GSR_ENCODER_VIDEO_H */ diff --git a/include/pipewire_audio.h b/include/pipewire_audio.h index 10d8c9b..68e5356 100644 --- a/include/pipewire_audio.h +++ b/include/pipewire_audio.h @@ -8,12 +8,6 @@ #include <stdbool.h> -#define GSR_PIPEWIRE_AUDIO_MAX_STREAM_NODES 128 -#define GSR_PIPEWIRE_AUDIO_MAX_PORTS 256 -#define GSR_PIPEWIRE_AUDIO_MAX_LINKS 256 -#define GSR_PIPEWIRE_AUDIO_MAX_REQUESTED_LINKS 32 -#define GSR_PIPEWIRE_AUDIO_MAX_VIRTUAL_SINKS 32 - typedef enum { GSR_PIPEWIRE_AUDIO_NODE_TYPE_STREAM_OUTPUT, /* Application audio */ GSR_PIPEWIRE_AUDIO_NODE_TYPE_STREAM_INPUT, /* Audio recording input */ @@ -84,20 +78,25 @@ typedef struct { char default_output_device_name[128]; char default_input_device_name[128]; - gsr_pipewire_audio_node stream_nodes[GSR_PIPEWIRE_AUDIO_MAX_STREAM_NODES]; - int num_stream_nodes; + gsr_pipewire_audio_node *stream_nodes; + size_t num_stream_nodes; + size_t stream_nodes_capacity_items; - gsr_pipewire_audio_port ports[GSR_PIPEWIRE_AUDIO_MAX_PORTS]; - int num_ports; + gsr_pipewire_audio_port *ports; + size_t num_ports; + size_t ports_capacity_items; - gsr_pipewire_audio_link links[GSR_PIPEWIRE_AUDIO_MAX_LINKS]; - int num_links; + gsr_pipewire_audio_link *links; + size_t num_links; + size_t links_capacity_items; - gsr_pipewire_audio_requested_link requested_links[GSR_PIPEWIRE_AUDIO_MAX_REQUESTED_LINKS]; - int num_requested_links; + gsr_pipewire_audio_requested_link *requested_links; + size_t num_requested_links; + size_t requested_links_capacity_items; - struct pw_proxy *virtual_sink_proxies[GSR_PIPEWIRE_AUDIO_MAX_VIRTUAL_SINKS]; - int num_virtual_sink_proxies; + struct pw_proxy **virtual_sink_proxies; + size_t num_virtual_sink_proxies; + size_t virtual_sink_proxies_capacity_items; } gsr_pipewire_audio; bool gsr_pipewire_audio_init(gsr_pipewire_audio *self); diff --git a/include/pipewire_video.h b/include/pipewire_video.h index 92622b8..d98e43d 100644 --- a/include/pipewire_video.h +++ b/include/pipewire_video.h @@ -9,7 +9,7 @@ #include <spa/param/video/format.h> #define GSR_PIPEWIRE_VIDEO_MAX_MODIFIERS 1024 -#define GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS 12 +#define GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS 6 #define GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES 4 typedef struct gsr_egl gsr_egl; @@ -65,6 +65,7 @@ typedef struct { struct spa_video_info format; int server_version_sync; bool negotiated; + bool renegotiated; bool damaged; struct { @@ -94,6 +95,9 @@ typedef struct { uint64_t modifiers[GSR_PIPEWIRE_VIDEO_MAX_MODIFIERS]; size_t num_modifiers; + + bool paused; + double paused_start_secs; } gsr_pipewire_video; /* @@ -108,5 +112,6 @@ 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_pipewire_video_region *region, gsr_pipewire_video_region *cursor_region, gsr_pipewire_video_dmabuf_data *dmabuf_data, int *num_dmabuf_data, uint32_t *fourcc, uint64_t *modifiers, bool *using_external_image); 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 */ diff --git a/include/replay_buffer/replay_buffer.h b/include/replay_buffer/replay_buffer.h new file mode 100644 index 0000000..a04a3be --- /dev/null +++ b/include/replay_buffer/replay_buffer.h @@ -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 */
\ No newline at end of file diff --git a/include/replay_buffer/replay_buffer_disk.h b/include/replay_buffer/replay_buffer_disk.h new file mode 100644 index 0000000..6873bb0 --- /dev/null +++ b/include/replay_buffer/replay_buffer_disk.h @@ -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 */
\ No newline at end of file diff --git a/include/replay_buffer/replay_buffer_ram.h b/include/replay_buffer/replay_buffer_ram.h new file mode 100644 index 0000000..a43d1b9 --- /dev/null +++ b/include/replay_buffer/replay_buffer_ram.h @@ -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 */
\ No newline at end of file diff --git a/include/shader.h b/include/shader.h index 8bc1104..285758d 100644 --- a/include/shader.h +++ b/include/shader.h @@ -1,6 +1,8 @@ #ifndef GSR_SHADER_H #define GSR_SHADER_H +#include <stdbool.h> + typedef struct gsr_egl gsr_egl; typedef struct { @@ -16,4 +18,6 @@ int gsr_shader_bind_attribute_location(gsr_shader *self, const char *attribute, 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 */ diff --git a/include/utils.h b/include/utils.h index b6f51c1..74ccf18 100644 --- a/include/utils.h +++ b/include/utils.h @@ -7,8 +7,6 @@ #include <stdbool.h> #include <stdint.h> -#define CONNECTOR_TYPE_COUNTS 32 - typedef struct AVCodecContext AVCodecContext; typedef struct AVFrame AVFrame; @@ -29,12 +27,6 @@ typedef struct { bool found_monitor; } get_monitor_by_name_userdata; -typedef struct { - int type; - int count; - int count_active; -} drm_connector_type_count; - 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); @@ -46,7 +38,7 @@ bool get_monitor_by_name(const gsr_egl *egl, gsr_connection_type connection_type 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); -drm_connector_type_count* drm_connector_types_get_index(drm_connector_type_count *type_counts, int *num_type_counts, int connector_type); +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); @@ -61,7 +53,6 @@ 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); -bool video_codec_context_is_vaapi(AVCodecContext *video_codec_context); vec2i scale_keep_aspect_ratio(vec2i from, vec2i to); |