diff options
| -rw-r--r-- | include/encoder/encoder.h | 6 | ||||
| -rw-r--r-- | include/recorder/recorder.h | 3 | ||||
| -rw-r--r-- | include/replay_buffer/replay_buffer.h | 8 | ||||
| -rw-r--r-- | src/cli/main.c | 2 | ||||
| -rw-r--r-- | src/encoder/encoder.c | 13 | ||||
| -rw-r--r-- | src/recorder/recorder.c | 6 | ||||
| -rw-r--r-- | src/replay_buffer/replay_buffer.c | 5 | ||||
| -rw-r--r-- | src/replay_buffer/replay_buffer_disk.c | 2 | ||||
| -rw-r--r-- | src/replay_buffer/replay_buffer_ram.c | 6 |
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; |
