aboutsummaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2026-08-01 23:02:07 +0200
committerdec05eba <dec05eba@protonmail.com>2026-08-01 23:02:07 +0200
commit40b6a13d14680cfacb3cdb59f04224540b80d9e4 (patch)
treed50c5eb6ae5de196e9ae90207bc172f719169866 /include
parentbd12a0ede46bbd92510f1cd82b04383e4a9e83c8 (diff)
Move muxing and replay saving from main.cpp into muxer and replay_save modules
Replay saving uses a pthread with an owning result struct instead of std::future and a global output filepath.
Diffstat (limited to 'include')
-rw-r--r--include/recorder/muxer.h40
-rw-r--r--include/recorder/replay_save.h53
2 files changed, 93 insertions, 0 deletions
diff --git a/include/recorder/muxer.h b/include/recorder/muxer.h
new file mode 100644
index 0000000..e47cdde
--- /dev/null
+++ b/include/recorder/muxer.h
@@ -0,0 +1,40 @@
+#ifndef GSR_RECORDER_MUXER_H
+#define GSR_RECORDER_MUXER_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <limits.h>
+#include "audio_capture.h"
+#include "capture_setup.h"
+#include "settings.h"
+
+#include <libavformat/avformat.h>
+
+typedef struct {
+ const gsr_audio_track *audio_track;
+ AVStream *stream;
+} gsr_recording_audio_stream;
+
+typedef struct {
+ AVFormatContext *av_format_context;
+ AVStream *video_stream;
+ gsr_recording_audio_stream *audio_streams;
+ size_t num_audio_streams;
+} gsr_recording_output;
+
+AVStream* create_stream(AVFormatContext *av_format_context, AVCodecContext *codec_context);
+bool add_hdr_metadata_to_video_stream(gsr_capture *cap, AVStream *video_stream);
+void set_format_context_options(AVFormatContext *av_format_context);
+void av_write_header(AVFormatContext *av_format_context, const char *ffmpeg_opts);
+
+/* Returns false on failure. Creates the output file and its video and audio streams */
+bool gsr_recording_output_start(gsr_recording_output *self, const char *filename, const gsr_recorder_settings *settings, AVCodecContext *video_codec_context, const gsr_audio_capture *audio_capture, bool hdr, gsr_video_sources *video_sources);
+bool gsr_recording_output_stop(gsr_recording_output *self);
+gsr_recording_audio_stream* gsr_recording_output_get_audio_stream_by_index(gsr_recording_output *self, int stream_index);
+
+/* |filepath| should be at least PATH_MAX bytes in size. Creates the directories of the filepath */
+bool gsr_create_new_recording_filepath_from_timestamp(char *filepath, size_t filepath_size, const char *directory, const char *filename_prefix, const char *file_extension, bool date_folders);
+
+size_t calculate_estimated_replay_buffer_packets(int64_t replay_buffer_size_secs, int fps, gsr_audio_codec audio_codec, const gsr_audio_input_tracks *audio_inputs);
+
+#endif /* GSR_RECORDER_MUXER_H */
diff --git a/include/recorder/replay_save.h b/include/recorder/replay_save.h
new file mode 100644
index 0000000..d92a8c0
--- /dev/null
+++ b/include/recorder/replay_save.h
@@ -0,0 +1,53 @@
+#ifndef GSR_RECORDER_REPLAY_SAVE_H
+#define GSR_RECORDER_REPLAY_SAVE_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <limits.h>
+#include <pthread.h>
+#include <signal.h>
+#include "muxer.h"
+#include "audio_capture.h"
+#include "capture_setup.h"
+#include "settings.h"
+
+#include "../encoder/encoder.h"
+#include "../replay_buffer/replay_buffer.h"
+
+#define GSR_SAVE_REPLAY_SECONDS_FULL -1
+
+typedef struct {
+ int64_t pts_offset;
+ int stream_index;
+} gsr_audio_pts_offset;
+
+/* Saves the replay buffer to a file on a separate thread */
+typedef struct {
+ pthread_t thread;
+ bool thread_created;
+ volatile sig_atomic_t finished;
+ bool success;
+ char output_filepath[PATH_MAX];
+
+ AVCodecContext *video_codec_context;
+ int video_stream_index;
+ gsr_recording_output recording_output;
+ gsr_replay_buffer_iterator video_start_iterator;
+ int64_t video_pts_offset;
+ gsr_audio_pts_offset *audio_pts_offsets;
+ size_t num_audio_pts_offsets;
+ gsr_replay_buffer *cloned_replay_buffer;
+ gsr_encoder *encoder;
+} gsr_replay_save;
+
+void gsr_replay_save_init(gsr_replay_save *self);
+bool gsr_replay_save_is_running(const gsr_replay_save *self);
+
+/* Returns false if the replay failed to start. |current_save_replay_seconds| can be GSR_SAVE_REPLAY_SECONDS_FULL to save the whole replay buffer */
+bool gsr_replay_save_start(gsr_replay_save *self, AVCodecContext *video_codec_context, int video_stream_index, const gsr_audio_capture *audio_capture, gsr_encoder *encoder, const gsr_recorder_settings *settings, const char *file_extension, bool hdr, gsr_video_sources *video_sources, int current_save_replay_seconds);
+/* Returns true when the replay finished saving, in which case |success| and |output_filepath| are set. |output_filepath| is empty when nothing was saved */
+bool gsr_replay_save_poll(gsr_replay_save *self, bool *success, const char **output_filepath);
+/* Waits for an ongoing replay save to finish. Returns the same values as gsr_replay_save_poll */
+bool gsr_replay_save_join(gsr_replay_save *self, bool *success, const char **output_filepath);
+
+#endif /* GSR_RECORDER_REPLAY_SAVE_H */