Add -replay-storage option to specify if temporary replay data should be stored in ram or disk

This commit is contained in:
dec05eba
2025-05-04 20:36:34 +02:00
parent 2ca5f3361c
commit 36c74d3411
17 changed files with 1010 additions and 330 deletions

View File

@@ -8,8 +8,7 @@
typedef struct gsr_egl gsr_egl;
#define NUM_ARGS 29
#define WINDOW_STR_MAX_SIZE 128
#define NUM_ARGS 30
typedef enum {
ARG_TYPE_STRING,
@@ -68,7 +67,8 @@ typedef struct {
gsr_audio_codec audio_codec;
gsr_bitrate_mode bitrate_mode;
gsr_video_quality video_quality;
char window[WINDOW_STR_MAX_SIZE];
gsr_replay_storage replay_storage;
char window[64];
const char *container_format;
const char *filename;
const char *replay_recording_directory;

View File

@@ -10,7 +10,7 @@ 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 {
@@ -23,13 +23,13 @@ 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 {
@@ -88,14 +88,19 @@ typedef enum {
typedef enum {
GSR_COLOR_RANGE_LIMITED,
GSR_COLOR_RANGE_FULL
GSR_COLOR_RANGE_FULL,
} gsr_color_range;
typedef enum {
GSR_COLOR_DEPTH_8_BITS,
GSR_COLOR_DEPTH_10_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);

View File

@@ -1,7 +1,7 @@
#ifndef GSR_ENCODER_H
#define GSR_ENCODER_H
#include "../replay_buffer.h"
#include "../replay_buffer/replay_buffer.h"
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
@@ -23,8 +23,7 @@ typedef struct {
} gsr_encoder_recording_destination;
typedef struct {
gsr_replay_buffer replay_buffer;
bool has_replay_buffer;
gsr_replay_buffer *replay_buffer;
pthread_mutex_t file_write_mutex;
bool mutex_created;
@@ -33,7 +32,7 @@ typedef struct {
size_t recording_destination_id_counter;
} gsr_encoder;
bool gsr_encoder_init(gsr_encoder *self, size_t replay_buffer_num_packets);
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);

View File

@@ -1,43 +0,0 @@
#ifndef GSR_REPLAY_BUFFER_H
#define GSR_REPLAY_BUFFER_H
#include <pthread.h>
#include <stdbool.h>
#include <libavcodec/packet.h>
typedef struct gsr_replay_buffer gsr_replay_buffer;
typedef struct {
AVPacket packet;
int ref_counter;
double timestamp;
} gsr_av_packet;
gsr_av_packet* gsr_av_packet_create(const AVPacket *av_packet, double timestamp);
gsr_av_packet* gsr_av_packet_ref(gsr_av_packet *self);
void gsr_av_packet_unref(gsr_av_packet *self);
struct gsr_replay_buffer {
gsr_av_packet **packets;
size_t capacity_num_packets;
size_t num_packets;
size_t index;
pthread_mutex_t mutex;
bool mutex_initialized;
gsr_replay_buffer *original_replay_buffer;
};
bool gsr_replay_buffer_init(gsr_replay_buffer *self, size_t replay_buffer_num_packets);
void gsr_replay_buffer_deinit(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);
gsr_av_packet* gsr_replay_buffer_get_packet_at_index(gsr_replay_buffer *self, size_t index);
/* The clone has to be deinitialized before the replay buffer it clones */
bool gsr_replay_buffer_clone(gsr_replay_buffer *self, gsr_replay_buffer *destination);
/* Returns 0 if replay buffer is empty */
size_t gsr_replay_buffer_find_packet_index_by_time_passed(gsr_replay_buffer *self, int seconds);
/* Returns -1 if not found */
size_t gsr_replay_buffer_find_keyframe(gsr_replay_buffer *self, size_t start_index, int stream_index, bool invert_stream_index);
#endif /* GSR_REPLAY_BUFFER_H */

View 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 */

View 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 */

View 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 */