aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/encoder/encoder.h6
-rw-r--r--include/recorder/recorder.h3
-rw-r--r--include/replay_buffer/replay_buffer.h8
-rw-r--r--src/cli/main.c2
-rw-r--r--src/encoder/encoder.c13
-rw-r--r--src/recorder/recorder.c6
-rw-r--r--src/replay_buffer/replay_buffer.c5
-rw-r--r--src/replay_buffer/replay_buffer_disk.c2
-rw-r--r--src/replay_buffer/replay_buffer_ram.c6
9 files changed, 40 insertions, 11 deletions
diff --git a/include/encoder/encoder.h b/include/encoder/encoder.h
index b46deb5..15009f1 100644
--- a/include/encoder/encoder.h
+++ b/include/encoder/encoder.h
@@ -41,7 +41,11 @@ typedef struct {
} 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);
+/*
+ When |exiting| is set the memory of the replay buffer is left to the operating system to free, which makes
+ this much faster when the replay buffer holds several gigabytes of data. See gsr_replay_buffer_destroy_at_exit.
+*/
+void gsr_encoder_deinit(gsr_encoder *self, bool exiting);
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 */
diff --git a/include/recorder/recorder.h b/include/recorder/recorder.h
index 5721a98..9ff13bd 100644
--- a/include/recorder/recorder.h
+++ b/include/recorder/recorder.h
@@ -39,7 +39,8 @@ typedef struct {
/* Returns NULL on failure and sets |error| to a |gsr_error| value */
gsr_recorder* gsr_recorder_create(const gsr_recorder_params *params, const gsr_recorder_callbacks *callbacks, int *error);
-void gsr_recorder_destroy(gsr_recorder *self);
+/* This is only called when the program is exiting, so memory that the operating system frees on exit isn't free'd. Only set exiting to true if the program is exiting */
+void gsr_recorder_destroy(gsr_recorder *self, bool exiting);
/* Returns a |gsr_error| value. Records until gsr_recorder_stop is called or until the capture target is gone */
int gsr_recorder_run(gsr_recorder *self);
diff --git a/include/replay_buffer/replay_buffer.h b/include/replay_buffer/replay_buffer.h
index c036b1c..3ac452a 100644
--- a/include/replay_buffer/replay_buffer.h
+++ b/include/replay_buffer/replay_buffer.h
@@ -14,6 +14,7 @@ typedef struct {
struct gsr_replay_buffer {
void (*destroy)(gsr_replay_buffer *self);
+ void (*destroy_at_exit)(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);
@@ -32,6 +33,13 @@ struct gsr_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);
+/*
+ Only frees the resources that the operating system doesn't free when the process exits, such as files,
+ and leaves the memory to the operating system to free. Freeing a replay buffer that holds several gigabytes
+ of data takes seconds, which is time wasted when the process is exiting anyway.
+ |self| can't be used after this.
+*/
+void gsr_replay_buffer_destroy_at_exit(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);
diff --git a/src/cli/main.c b/src/cli/main.c
index ac7de24..aaa315c 100644
--- a/src/cli/main.c
+++ b/src/cli/main.c
@@ -500,7 +500,7 @@ static int record(args_parser *arg_parser, gsr_windowing *windowing, gsr_capture
gsr_ipc_complete_request(ipc, GSR_IPC_DEFERRED_REQUEST_STOP, true, arg_parser->settings.is_replaying ? NULL : arg_parser->settings.filename);
gsr_ipc_stop(ipc);
- gsr_recorder_destroy(recorder);
+ gsr_recorder_destroy(recorder, true);
recorder = NULL;
return run_result;
}
diff --git a/src/encoder/encoder.c b/src/encoder/encoder.c
index 3aebb7a..e9b71d7 100644
--- a/src/encoder/encoder.c
+++ b/src/encoder/encoder.c
@@ -44,14 +44,14 @@ bool gsr_encoder_init(gsr_encoder *self, gsr_replay_storage replay_storage, size
if(pthread_mutex_init(&self->file_write_mutex, NULL) != 0) {
gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_encoder_init: failed to create mutex");
- gsr_encoder_deinit(self);
+ gsr_encoder_deinit(self, false);
return false;
}
self->file_write_mutex_created = true;
if(pthread_mutex_init(&self->replay_mutex, NULL) != 0) {
gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_encoder_init: failed to create mutex");
- gsr_encoder_deinit(self);
+ gsr_encoder_deinit(self, false);
return false;
}
self->replay_mutex_created = true;
@@ -60,7 +60,7 @@ bool gsr_encoder_init(gsr_encoder *self, gsr_replay_storage replay_storage, size
self->replay_buffer = gsr_replay_buffer_create(replay_storage, replay_directory, replay_buffer_time, replay_buffer_num_packets);
if(!self->replay_buffer) {
gsr_log(GSR_LOG_LEVEL_ERROR, "gsr_encoder_init: failed to create replay buffer");
- gsr_encoder_deinit(self);
+ gsr_encoder_deinit(self, false);
return false;
}
}
@@ -68,7 +68,7 @@ bool gsr_encoder_init(gsr_encoder *self, gsr_replay_storage replay_storage, size
return true;
}
-void gsr_encoder_deinit(gsr_encoder *self) {
+void gsr_encoder_deinit(gsr_encoder *self, bool exiting) {
if(self->file_write_mutex_created)
pthread_mutex_lock(&self->file_write_mutex);
for(size_t i = 0; i < self->num_recording_destinations; ++i) {
@@ -81,7 +81,10 @@ void gsr_encoder_deinit(gsr_encoder *self) {
if(self->replay_buffer) {
pthread_mutex_lock(&self->replay_mutex);
- gsr_replay_buffer_destroy(self->replay_buffer);
+ if(exiting)
+ gsr_replay_buffer_destroy_at_exit(self->replay_buffer);
+ else
+ gsr_replay_buffer_destroy(self->replay_buffer);
self->replay_buffer = NULL;
pthread_mutex_unlock(&self->replay_mutex);
}
diff --git a/src/recorder/recorder.c b/src/recorder/recorder.c
index 949ed99..f24495c 100644
--- a/src/recorder/recorder.c
+++ b/src/recorder/recorder.c
@@ -450,7 +450,7 @@ gsr_recorder* gsr_recorder_create(const gsr_recorder_params *params, const gsr_r
fail:
*error = error_code;
- gsr_recorder_destroy(self);
+ gsr_recorder_destroy(self, false);
return NULL;
}
@@ -892,7 +892,7 @@ static void gsr_recorder_stop_recording(gsr_recorder *self) {
self->callbacks.recording_stopped(self->settings.filename, self->callbacks.userdata);
}
-void gsr_recorder_destroy(gsr_recorder *self) {
+void gsr_recorder_destroy(gsr_recorder *self, bool exiting) {
if(!self)
return;
@@ -909,7 +909,7 @@ void gsr_recorder_destroy(gsr_recorder *self) {
gsr_video_encoder_destroy(self->video_encoder, self->video_codec_context);
if(self->encoder_initialized)
- gsr_encoder_deinit(&self->encoder);
+ gsr_encoder_deinit(&self->encoder, exiting);
gsr_video_sources_deinit(&self->video_sources_data);
diff --git a/src/replay_buffer/replay_buffer.c b/src/replay_buffer/replay_buffer.c
index 458b359..4958bba 100644
--- a/src/replay_buffer/replay_buffer.c
+++ b/src/replay_buffer/replay_buffer.c
@@ -22,6 +22,11 @@ void gsr_replay_buffer_destroy(gsr_replay_buffer *self) {
free(self);
}
+void gsr_replay_buffer_destroy_at_exit(gsr_replay_buffer *self) {
+ self->destroy_at_exit(self);
+ /* |self| is intentionally not free'd, the operating system does that when the process exits */
+}
+
bool gsr_replay_buffer_append(gsr_replay_buffer *self, const AVPacket *av_packet, double timestamp) {
return self->append(self, av_packet, timestamp);
}
diff --git a/src/replay_buffer/replay_buffer_disk.c b/src/replay_buffer/replay_buffer_disk.c
index 56244f9..da82df5 100644
--- a/src/replay_buffer/replay_buffer_disk.c
+++ b/src/replay_buffer/replay_buffer_disk.c
@@ -423,6 +423,8 @@ static void get_current_time(char *time_str, size_t time_str_size) {
static void gsr_replay_buffer_disk_set_impl_funcs(gsr_replay_buffer_disk *self) {
self->replay_buffer.destroy = gsr_replay_buffer_disk_destroy;
+ /* The files and the directory have to be removed even when the process exits */
+ self->replay_buffer.destroy_at_exit = gsr_replay_buffer_disk_destroy;
self->replay_buffer.append = gsr_replay_buffer_disk_append;
self->replay_buffer.clear = gsr_replay_buffer_disk_clear;
self->replay_buffer.iterator_get_packet = gsr_replay_buffer_disk_iterator_get_packet;
diff --git a/src/replay_buffer/replay_buffer_ram.c b/src/replay_buffer/replay_buffer_ram.c
index 680517d..ce3914b 100644
--- a/src/replay_buffer/replay_buffer_ram.c
+++ b/src/replay_buffer/replay_buffer_ram.c
@@ -70,6 +70,11 @@ static void gsr_replay_buffer_ram_destroy(gsr_replay_buffer *replay_buffer) {
self->index = 0;
}
+/* The replay buffer only holds memory, which the operating system frees when the process exits */
+static void gsr_replay_buffer_ram_destroy_at_exit(gsr_replay_buffer *replay_buffer) {
+ (void)replay_buffer;
+}
+
static bool gsr_replay_buffer_ram_append(gsr_replay_buffer *replay_buffer, const AVPacket *av_packet, double timestamp) {
gsr_replay_buffer_ram *self = (gsr_replay_buffer_ram*)replay_buffer;
gsr_av_packet_ram *packet = gsr_av_packet_ram_create(av_packet, timestamp);
@@ -231,6 +236,7 @@ static bool gsr_replay_buffer_ram_iterator_next(gsr_replay_buffer *replay_buffer
static void gsr_replay_buffer_ram_set_impl_funcs(gsr_replay_buffer_ram *self) {
self->replay_buffer.destroy = gsr_replay_buffer_ram_destroy;
+ self->replay_buffer.destroy_at_exit = gsr_replay_buffer_ram_destroy_at_exit;
self->replay_buffer.append = gsr_replay_buffer_ram_append;
self->replay_buffer.clear = gsr_replay_buffer_ram_clear;
self->replay_buffer.iterator_get_packet = gsr_replay_buffer_ram_iterator_get_packet;