diff options
| author | dec05eba <dec05eba@protonmail.com> | 2026-08-01 23:02:07 +0200 |
|---|---|---|
| committer | dec05eba <dec05eba@protonmail.com> | 2026-08-01 23:02:07 +0200 |
| commit | 40b6a13d14680cfacb3cdb59f04224540b80d9e4 (patch) | |
| tree | d50c5eb6ae5de196e9ae90207bc172f719169866 /include | |
| parent | bd12a0ede46bbd92510f1cd82b04383e4a9e83c8 (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.h | 40 | ||||
| -rw-r--r-- | include/recorder/replay_save.h | 53 |
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 */ |
