diff options
Diffstat (limited to 'src/recorder/recorder.c')
| -rw-r--r-- | src/recorder/recorder.c | 166 |
1 files changed, 108 insertions, 58 deletions
diff --git a/src/recorder/recorder.c b/src/recorder/recorder.c index 4426ac5..4bffb8e 100644 --- a/src/recorder/recorder.c +++ b/src/recorder/recorder.c @@ -35,6 +35,15 @@ #define GSR_VIDEO_STREAM_INDEX 0 +#define GSR_SET_PAUSED_REQUEST_NONE -1 +#define GSR_SET_PAUSED_REQUEST_UNPAUSE 0 +#define GSR_SET_PAUSED_REQUEST_PAUSE 1 + +#define GSR_REPLAY_RECORDING_REQUEST_NONE 0 +#define GSR_REPLAY_RECORDING_REQUEST_TOGGLE 1 +#define GSR_REPLAY_RECORDING_REQUEST_START 2 +#define GSR_REPLAY_RECORDING_REQUEST_STOP 3 + struct gsr_recorder { gsr_recorder_settings settings; gsr_recorder_callbacks callbacks; @@ -88,7 +97,9 @@ struct gsr_recorder { atomic_int running; atomic_int toggle_pause; - atomic_int toggle_replay_recording; + atomic_int set_paused_request; + atomic_int replay_recording_request; + atomic_int replay_recording_state; atomic_int save_replay_seconds; bool should_stop_error; bool force_iframe_frame; @@ -403,7 +414,9 @@ gsr_recorder* gsr_recorder_create(const gsr_recorder_params *params, const gsr_r self->audio_input_tracks = params->audio_input_tracks; atomic_init(&self->running, 1); atomic_init(&self->toggle_pause, 0); - atomic_init(&self->toggle_replay_recording, 0); + atomic_init(&self->set_paused_request, GSR_SET_PAUSED_REQUEST_NONE); + atomic_init(&self->replay_recording_request, GSR_REPLAY_RECORDING_REQUEST_NONE); + atomic_init(&self->replay_recording_state, 0); atomic_init(&self->save_replay_seconds, 0); self->audio_max_frame_size = 1024; int error_code = GSR_ERROR_GENERIC; @@ -625,78 +638,99 @@ static void recorder_capture_and_encode_frame(gsr_recorder *self, bool damaged) } static void recorder_apply_pause_toggle(gsr_recorder *self) { - if(atomic_load(&self->toggle_pause) == 1 && !self->settings.is_replaying) { - self->paused = !self->paused; + const bool toggle_pause = atomic_exchange(&self->toggle_pause, 0) == 1; + const int set_paused_request = atomic_exchange(&self->set_paused_request, GSR_SET_PAUSED_REQUEST_NONE); + if(self->settings.is_replaying) + return; + + bool new_paused = self->paused; + if(toggle_pause) + new_paused = !new_paused; + if(set_paused_request != GSR_SET_PAUSED_REQUEST_NONE) + new_paused = set_paused_request == GSR_SET_PAUSED_REQUEST_PAUSE; + + if(new_paused != self->paused) { + self->paused = new_paused; gsr_recording_clock_set_paused(self->recording_clock, self->paused); gsr_log(GSR_LOG_LEVEL_INFO, self->paused ? "Paused" : "Unpaused"); - atomic_store(&self->toggle_pause, 0); } } static void recorder_apply_replay_recording_toggle(gsr_recorder *self) { - if(atomic_load(&self->toggle_replay_recording) && !self->settings.replay_recording_directory) { - atomic_store(&self->toggle_replay_recording, 0); - if(self->callbacks.recording_started) + const int request = atomic_exchange(&self->replay_recording_request, GSR_REPLAY_RECORDING_REQUEST_NONE); + if(request == GSR_REPLAY_RECORDING_REQUEST_NONE) + return; + + if(!self->settings.replay_recording_directory) { + if(request != GSR_REPLAY_RECORDING_REQUEST_STOP && self->callbacks.recording_started) self->callbacks.recording_started(NULL, self->callbacks.userdata); + return; } - if(atomic_load(&self->toggle_replay_recording) && self->settings.replay_recording_directory) { - atomic_store(&self->toggle_replay_recording, 0); - const bool new_replay_recording_state = !self->replay_recording; - if(new_replay_recording_state) { - gsr_audio_capture_lock_filter(&self->audio_capture); - self->num_replay_recording_items = 0; - const bool filepath_created = gsr_create_new_recording_filepath_from_timestamp(self->replay_recording_filepath, sizeof(self->replay_recording_filepath), self->settings.replay_recording_directory, "Video", self->file_extension, self->settings.date_folders); - if(filepath_created && gsr_recording_output_start(&self->replay_recording_output, self->replay_recording_filepath, &self->settings, self->video_codec_context, &self->audio_capture, self->hdr, self->video_sources)) { - const size_t video_recording_destination_id = gsr_encoder_add_recording_destination(&self->encoder, self->video_codec_context, self->replay_recording_output.av_format_context, self->replay_recording_output.video_stream, self->video_frame->pts); - if(self->settings.write_first_frame_ts && video_recording_destination_id != (size_t)-1) { - char ts_filepath[PATH_MAX + 4]; - snprintf(ts_filepath, sizeof(ts_filepath), "%s.ts", self->replay_recording_filepath); - gsr_encoder_set_recording_destination_first_frame_ts_filepath(&self->encoder, video_recording_destination_id, ts_filepath); - } - - if(video_recording_destination_id != (size_t)-1 && self->num_replay_recording_items < GSR_MAX_RECORDING_DESTINATIONS) { - self->replay_recording_items[self->num_replay_recording_items] = video_recording_destination_id; - ++self->num_replay_recording_items; - } + bool new_replay_recording_state = !self->replay_recording; + if(request == GSR_REPLAY_RECORDING_REQUEST_START) + new_replay_recording_state = true; + else if(request == GSR_REPLAY_RECORDING_REQUEST_STOP) + new_replay_recording_state = false; - for(size_t i = 0; i < self->replay_recording_output.num_audio_streams; ++i) { - const gsr_recording_audio_stream *audio_stream = &self->replay_recording_output.audio_streams[i]; - const size_t audio_recording_destination_id = gsr_encoder_add_recording_destination(&self->encoder, audio_stream->audio_track->codec_context, self->replay_recording_output.av_format_context, audio_stream->stream, audio_stream->audio_track->pts); - if(audio_recording_destination_id != (size_t)-1 && self->num_replay_recording_items < GSR_MAX_RECORDING_DESTINATIONS) { - self->replay_recording_items[self->num_replay_recording_items] = audio_recording_destination_id; - ++self->num_replay_recording_items; - } - } + if(new_replay_recording_state == self->replay_recording) + return; - self->replay_recording = true; - self->force_iframe_frame = true; - gsr_log(GSR_LOG_LEVEL_INFO, "Started recording"); - if(self->callbacks.recording_started) - self->callbacks.recording_started(self->replay_recording_filepath, self->callbacks.userdata); - } else { - if(self->callbacks.recording_started) - self->callbacks.recording_started(NULL, self->callbacks.userdata); + if(new_replay_recording_state) { + gsr_audio_capture_lock_filter(&self->audio_capture); + self->num_replay_recording_items = 0; + const bool filepath_created = gsr_create_new_recording_filepath_from_timestamp(self->replay_recording_filepath, sizeof(self->replay_recording_filepath), self->settings.replay_recording_directory, "Video", self->file_extension, self->settings.date_folders); + if(filepath_created && gsr_recording_output_start(&self->replay_recording_output, self->replay_recording_filepath, &self->settings, self->video_codec_context, &self->audio_capture, self->hdr, self->video_sources)) { + const size_t video_recording_destination_id = gsr_encoder_add_recording_destination(&self->encoder, self->video_codec_context, self->replay_recording_output.av_format_context, self->replay_recording_output.video_stream, self->video_frame->pts); + if(self->settings.write_first_frame_ts && video_recording_destination_id != (size_t)-1) { + char ts_filepath[PATH_MAX + 4]; + snprintf(ts_filepath, sizeof(ts_filepath), "%s.ts", self->replay_recording_filepath); + gsr_encoder_set_recording_destination_first_frame_ts_filepath(&self->encoder, video_recording_destination_id, ts_filepath); } - gsr_audio_capture_unlock_filter(&self->audio_capture); - } else if(self->replay_recording_output.av_format_context) { - for(size_t i = 0; i < self->num_replay_recording_items; ++i) { - gsr_encoder_remove_recording_destination(&self->encoder, self->replay_recording_items[i]); + + if(video_recording_destination_id != (size_t)-1 && self->num_replay_recording_items < GSR_MAX_RECORDING_DESTINATIONS) { + self->replay_recording_items[self->num_replay_recording_items] = video_recording_destination_id; + ++self->num_replay_recording_items; } - self->num_replay_recording_items = 0; - if(gsr_recording_output_stop(&self->replay_recording_output)) { - gsr_log(GSR_LOG_LEVEL_INFO, "Stopped recording"); - if(self->callbacks.recording_stopped) - self->callbacks.recording_stopped(self->replay_recording_filepath, self->callbacks.userdata); - } else { - if(self->callbacks.recording_stopped) - self->callbacks.recording_stopped(NULL, self->callbacks.userdata); + for(size_t i = 0; i < self->replay_recording_output.num_audio_streams; ++i) { + const gsr_recording_audio_stream *audio_stream = &self->replay_recording_output.audio_streams[i]; + const size_t audio_recording_destination_id = gsr_encoder_add_recording_destination(&self->encoder, audio_stream->audio_track->codec_context, self->replay_recording_output.av_format_context, audio_stream->stream, audio_stream->audio_track->pts); + if(audio_recording_destination_id != (size_t)-1 && self->num_replay_recording_items < GSR_MAX_RECORDING_DESTINATIONS) { + self->replay_recording_items[self->num_replay_recording_items] = audio_recording_destination_id; + ++self->num_replay_recording_items; + } } - self->replay_recording = false; - self->replay_recording_filepath[0] = '\0'; + self->replay_recording = true; + atomic_store(&self->replay_recording_state, 1); + self->force_iframe_frame = true; + gsr_log(GSR_LOG_LEVEL_INFO, "Started recording"); + if(self->callbacks.recording_started) + self->callbacks.recording_started(self->replay_recording_filepath, self->callbacks.userdata); + } else { + if(self->callbacks.recording_started) + self->callbacks.recording_started(NULL, self->callbacks.userdata); } + gsr_audio_capture_unlock_filter(&self->audio_capture); + } else if(self->replay_recording_output.av_format_context) { + for(size_t i = 0; i < self->num_replay_recording_items; ++i) { + gsr_encoder_remove_recording_destination(&self->encoder, self->replay_recording_items[i]); + } + self->num_replay_recording_items = 0; + + if(gsr_recording_output_stop(&self->replay_recording_output)) { + gsr_log(GSR_LOG_LEVEL_INFO, "Stopped recording"); + if(self->callbacks.recording_stopped) + self->callbacks.recording_stopped(self->replay_recording_filepath, self->callbacks.userdata); + } else { + if(self->callbacks.recording_stopped) + self->callbacks.recording_stopped(NULL, self->callbacks.userdata); + } + + self->replay_recording = false; + atomic_store(&self->replay_recording_state, 0); + self->replay_recording_filepath[0] = '\0'; } } @@ -905,8 +939,24 @@ void gsr_recorder_toggle_pause(gsr_recorder *self) { atomic_store(&self->toggle_pause, 1); } +void gsr_recorder_set_paused(gsr_recorder *self, bool paused) { + atomic_store(&self->set_paused_request, paused ? GSR_SET_PAUSED_REQUEST_PAUSE : GSR_SET_PAUSED_REQUEST_UNPAUSE); +} + void gsr_recorder_toggle_replay_recording(gsr_recorder *self) { - atomic_store(&self->toggle_replay_recording, 1); + atomic_store(&self->replay_recording_request, GSR_REPLAY_RECORDING_REQUEST_TOGGLE); +} + +void gsr_recorder_start_replay_recording(gsr_recorder *self) { + atomic_store(&self->replay_recording_request, GSR_REPLAY_RECORDING_REQUEST_START); +} + +void gsr_recorder_stop_replay_recording(gsr_recorder *self) { + atomic_store(&self->replay_recording_request, GSR_REPLAY_RECORDING_REQUEST_STOP); +} + +bool gsr_recorder_is_replay_recording(const gsr_recorder *self) { + return atomic_load(&self->replay_recording_state) == 1; } void gsr_recorder_save_replay(gsr_recorder *self, int seconds) { |
