Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/sphinx/reference-frontend-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ Structures/Enumerations

Triggered when the replay buffer has fully stopped.

- **OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVING**

Triggered when the replay buffer is saving.

- **OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED**

Triggered when the replay buffer has been saved.
Expand Down
2 changes: 2 additions & 0 deletions frontend/api/obs-frontend-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ enum obs_frontend_event {

OBS_FRONTEND_EVENT_CANVAS_ADDED,
OBS_FRONTEND_EVENT_CANVAS_REMOVED,

OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVING,
};

/* ------------------------------------------------------------------------- */
Expand Down
2 changes: 1 addition & 1 deletion frontend/widgets/OBSBasic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ private slots:

obs_hotkey_pair_id streamingHotkeys, recordingHotkeys, pauseHotkeys, replayBufHotkeys, vcamHotkeys,
togglePreviewHotkeys, contextBarHotkeys;
obs_hotkey_id forceStreamingStopHotkey, splitFileHotkey, addChapterHotkey;
obs_hotkey_id forceStreamingStopHotkey, splitFileHotkey, addChapterHotkey, replayBufSaveHotkey;

void InitHotkeys();
void CreateHotkeys();
Expand Down
24 changes: 24 additions & 0 deletions frontend/widgets/OBSBasic_Hotkeys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,30 @@ void OBSBasic::CreateHotkeys()
this, this);
LoadHotkeyPair(replayBufHotkeys, "OBSBasic.StartReplayBuffer", "OBSBasic.StopReplayBuffer");

auto replayBufferCallback = [](void *data, obs_hotkey_id, obs_hotkey_t *, bool pressed) {
OBSBasic *basic = static_cast<OBSBasic *>(data);
if (basic->outputHandler->ReplayBufferActive() && pressed) {
blog(LOG_INFO, "Saving replay buffer due to hotkey");
basic->ReplayBufferSave();
}
};

replayBufSaveHotkey = obs_hotkey_register_frontend("OBSBasic.SaveReplayBuffer", Str("Basic.Main.SaveReplay"),
replayBufferCallback, this);

const char *exists = config_get_string(activeConfiguration, "Hotkeys", "OBSBasic.SaveReplayBuffer");
if (exists) {
LoadHotkey(replayBufSaveHotkey, "OBSBasic.SaveReplayBuffer");
} else {
OBSDataArrayAutoRelease array = obs_data_get_array(LoadHotkeyData("ReplayBuffer"), "ReplayBuffer.Save");
obs_hotkey_load(replayBufSaveHotkey, array);

OBSDataAutoRelease newData = obs_data_create();
obs_data_set_array(newData, "bindings", array);
config_set_string(activeConfiguration, "Hotkeys", "OBSBasic.SaveReplayBuffer",
obs_data_get_json(newData));
}

if (vcamEnabled) {
vcamHotkeys = obs_hotkey_pair_register_frontend(
"OBSBasic.StartVirtualCam", Str("Basic.Main.StartVirtualCam"), "OBSBasic.StopVirtualCam",
Expand Down
2 changes: 2 additions & 0 deletions frontend/widgets/OBSBasic_ReplayBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ void OBSBasic::ReplayBufferSave()
if (!outputHandler->ReplayBufferActive())
return;

OnEvent(OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVING);

calldata_t cd = {0};
proc_handler_t *ph = obs_output_get_proc_handler(outputHandler->replayBuffer);
proc_handler_call(ph, "save", &cd);
Expand Down
1 change: 0 additions & 1 deletion plugins/obs-ffmpeg/data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ MediaFileFilter.AudioFiles="Audio Files"
MediaFileFilter.AllFiles="All Files"

ReplayBuffer="Replay Buffer"
ReplayBuffer.Save="Save Replay"

HelperProcessFailed="Unable to start the recording helper process. Check that OBS files have not been blocked or removed by any 3rd party antivirus / security software."
UnableToWritePath="Unable to write to %1. Make sure you're using a recording path which your user account is allowed to write to and that there is sufficient disk space."
Expand Down
27 changes: 9 additions & 18 deletions plugins/obs-ffmpeg/obs-ffmpeg-mux.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,30 +914,20 @@ static const char *replay_buffer_getname(void *type)
return obs_module_text("ReplayBuffer");
}

static void replay_buffer_hotkey(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey, bool pressed)
static void save_replay_proc(void *data, calldata_t *cd)
{
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(hotkey);

if (!pressed)
return;

struct ffmpeg_muxer *stream = data;

if (os_atomic_load_bool(&stream->active)) {
obs_encoder_t *vencoder = obs_output_get_video_encoder(stream->output);
if (obs_encoder_paused(vencoder)) {
info("Could not save buffer because encoders paused");
info("Could not save buffer because the encoder is paused");
return;
}

stream->save_ts = os_gettime_ns() / 1000LL;
}
}

static void save_replay_proc(void *data, calldata_t *cd)
{
replay_buffer_hotkey(data, 0, NULL, true);
UNUSED_PARAMETER(cd);
}

Expand All @@ -954,24 +944,19 @@ static void *replay_buffer_create(obs_data_t *settings, obs_output_t *output)
struct ffmpeg_muxer *stream = bzalloc(sizeof(*stream));
stream->output = output;

stream->hotkey = obs_hotkey_register_output(output, "ReplayBuffer.Save", obs_module_text("ReplayBuffer.Save"),
replay_buffer_hotkey, stream);

proc_handler_t *ph = obs_output_get_proc_handler(output);
proc_handler_add(ph, "void save()", save_replay_proc, stream);
proc_handler_add(ph, "void get_last_replay(out string path)", get_last_replay, stream);

signal_handler_t *sh = obs_output_get_signal_handler(output);
signal_handler_add(sh, "void saved()");
signal_handler_add(sh, "void saving(ptr output)");

return stream;
}

static void replay_buffer_destroy(void *data)
{
struct ffmpeg_muxer *stream = data;
if (stream->hotkey)
obs_hotkey_unregister(stream->hotkey);
ffmpeg_mux_destroy(data);
}

Expand Down Expand Up @@ -1154,6 +1139,12 @@ static void replay_buffer_save(struct ffmpeg_muxer *stream)
int64_t audio_offsets[MAX_AUDIO_MIXES] = {0};
int64_t audio_dts_offsets[MAX_AUDIO_MIXES] = {0};

calldata_t cd = {0};
calldata_set_ptr(&cd, "output", stream->output);
signal_handler_t *sh = obs_output_get_signal_handler(stream->output);
signal_handler_signal(sh, "saving", &cd);
calldata_free(&cd);

for (size_t i = 0; i < num_packets; i++) {
struct encoder_packet *pkt;
pkt = deque_data(&stream->packets, i * size);
Expand Down
Loading