Add ClosableStream support to ReplayBuffer
parent
3069c2e361
commit
25c1a1130c
|
@ -816,8 +816,7 @@ OBS::OBS()
|
||||||
|
|
||||||
OBS::~OBS()
|
OBS::~OBS()
|
||||||
{
|
{
|
||||||
Stop(true);
|
Stop(true, true);
|
||||||
StopReplayBuffer();
|
|
||||||
|
|
||||||
bShuttingDown = true;
|
bShuttingDown = true;
|
||||||
|
|
||||||
|
|
|
@ -850,6 +850,7 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<VideoFileStream> replayBufferStream;
|
std::unique_ptr<VideoFileStream> replayBufferStream;
|
||||||
ReplayBuffer *replayBuffer;
|
ReplayBuffer *replayBuffer;
|
||||||
|
StopInfo replayBufferStop;
|
||||||
|
|
||||||
bool bRequestKeyframe;
|
bool bRequestKeyframe;
|
||||||
int keyframeWait;
|
int keyframeWait;
|
||||||
|
@ -1017,11 +1018,11 @@ private:
|
||||||
void ResetItemCrops();
|
void ResetItemCrops();
|
||||||
|
|
||||||
void Start(bool recordingOnly=false, bool replayBufferOnly=false);
|
void Start(bool recordingOnly=false, bool replayBufferOnly=false);
|
||||||
void Stop(bool overrideKeepRecording=false);
|
void Stop(bool overrideKeepRecording=false, bool stopReplayBuffer=false);
|
||||||
bool StartRecording(bool force=false);
|
bool StartRecording(bool force=false);
|
||||||
void StopRecording();
|
void StopRecording();
|
||||||
void StartReplayBuffer();
|
void StartReplayBuffer();
|
||||||
void StopReplayBuffer();
|
void StopReplayBuffer(bool immediate=false);
|
||||||
|
|
||||||
static void STDCALL StartStreamHotkey(DWORD hotkey, UPARAM param, bool bDown);
|
static void STDCALL StartStreamHotkey(DWORD hotkey, UPARAM param, bool bDown);
|
||||||
static void STDCALL StopStreamHotkey(DWORD hotkey, UPARAM param, bool bDown);
|
static void STDCALL StopStreamHotkey(DWORD hotkey, UPARAM param, bool bDown);
|
||||||
|
|
|
@ -109,20 +109,32 @@ void OBS::StartReplayBuffer()
|
||||||
ConfigureStreamButtons();
|
ConfigureStreamButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBS::StopReplayBuffer()
|
void OBS::StopReplayBuffer(bool immediate)
|
||||||
{
|
{
|
||||||
if (!replayBufferStream) return;
|
if (!replayBufferStream) return;
|
||||||
|
|
||||||
|
if (!immediate && replayBufferStop.func) return;
|
||||||
|
|
||||||
|
auto shutdown = [this]()
|
||||||
|
{
|
||||||
bRecordingReplayBuffer = false;
|
bRecordingReplayBuffer = false;
|
||||||
ReportStopRecordingReplayBufferTrigger();
|
ReportStopRecordingReplayBufferTrigger();
|
||||||
|
|
||||||
if (!bStreaming && !bRecording && bRunning) Stop(true);
|
if (!bStreaming && !bRecording && bRunning) PostStopMessage(true);
|
||||||
|
|
||||||
auto stream = move(replayBufferStream);
|
auto stream = move(replayBufferStream);
|
||||||
|
|
||||||
replayBuffer = nullptr;
|
replayBuffer = nullptr;
|
||||||
|
|
||||||
ConfigureStreamButtons();
|
ConfigureStreamButtons();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (immediate)
|
||||||
|
return shutdown();
|
||||||
|
|
||||||
|
replayBufferStop.func = shutdown;
|
||||||
|
|
||||||
|
replayBufferStop.time = (DWORD)(GetVideoTime() - firstFrameTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
String ExpandRecordingFilename(String filename)
|
String ExpandRecordingFilename(String filename)
|
||||||
|
@ -876,7 +888,7 @@ retryHookTestV2:
|
||||||
ConfigureStreamButtons();
|
ConfigureStreamButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBS::Stop(bool overrideKeepRecording)
|
void OBS::Stop(bool overrideKeepRecording, bool stopReplayBuffer)
|
||||||
{
|
{
|
||||||
if((!bStreaming && !bRecording && !bRunning && !bRecordingReplayBuffer) && (!bTestStream)) return;
|
if((!bStreaming && !bRecording && !bRunning && !bRecordingReplayBuffer) && (!bTestStream)) return;
|
||||||
|
|
||||||
|
@ -886,7 +898,7 @@ void OBS::Stop(bool overrideKeepRecording)
|
||||||
|
|
||||||
int networkMode = AppConfig->GetInt(TEXT("Publish"), TEXT("Mode"), 2);
|
int networkMode = AppConfig->GetInt(TEXT("Publish"), TEXT("Mode"), 2);
|
||||||
|
|
||||||
if(((!overrideKeepRecording && bRecording && bKeepRecording) || bRecordingReplayBuffer) && networkMode == 0) {
|
if((!overrideKeepRecording && ((bRecording && bKeepRecording) || (!stopReplayBuffer && bRecordingReplayBuffer))) && networkMode == 0) {
|
||||||
videoEncoder->RequestKeyframe();
|
videoEncoder->RequestKeyframe();
|
||||||
|
|
||||||
Log(TEXT("=====Stream End (recording continues): %s========================="), CurrentDateTimeString().Array());
|
Log(TEXT("=====Stream End (recording continues): %s========================="), CurrentDateTimeString().Array());
|
||||||
|
@ -967,6 +979,7 @@ void OBS::Stop(bool overrideKeepRecording)
|
||||||
bStreaming = false;
|
bStreaming = false;
|
||||||
|
|
||||||
if(bRecording) StopRecording();
|
if(bRecording) StopRecording();
|
||||||
|
if (bRecordingReplayBuffer) StopReplayBuffer(true);
|
||||||
|
|
||||||
delete micAudio;
|
delete micAudio;
|
||||||
micAudio = NULL;
|
micAudio = NULL;
|
||||||
|
|
|
@ -217,10 +217,13 @@ void OBS::SendFrame(VideoSegment &curSegment, QWORD firstFrameTime)
|
||||||
if (fileStream)
|
if (fileStream)
|
||||||
fileStream->AddPacket(shared_data, curSegment.timestamp, curSegment.pts, packet.type);
|
fileStream->AddPacket(shared_data, curSegment.timestamp, curSegment.pts, packet.type);
|
||||||
if (replayBufferStream)
|
if (replayBufferStream)
|
||||||
|
{
|
||||||
|
if (!HandleStreamStopInfo(replayBufferStop, packet.type, curSegment))
|
||||||
replayBufferStream->AddPacket(shared_data, curSegment.timestamp, curSegment.pts, packet.type);
|
replayBufferStream->AddPacket(shared_data, curSegment.timestamp, curSegment.pts, packet.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool OBS::HandleStreamStopInfo(OBS::StopInfo &info, PacketType type, const VideoSegment& segment)
|
bool OBS::HandleStreamStopInfo(OBS::StopInfo &info, PacketType type, const VideoSegment& segment)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace
|
||||||
using packet_vec_t = deque<shared_ptr<const packet_t>>;
|
using packet_vec_t = deque<shared_ptr<const packet_t>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateRecordingHelper(VideoFileStream *&stream, packet_list_t &packets);
|
void CreateRecordingHelper(unique_ptr<VideoFileStream> &stream, packet_list_t &packets);
|
||||||
|
|
||||||
static DWORD STDCALL SaveReplayBufferThread(void *arg);
|
static DWORD STDCALL SaveReplayBufferThread(void *arg);
|
||||||
|
|
||||||
|
@ -66,6 +66,8 @@ struct ReplayBuffer : VideoFileStream
|
||||||
for (auto &thread : threads)
|
for (auto &thread : threads)
|
||||||
if (WaitForSingleObject(thread.second.get(), seconds * 100) != WAIT_OBJECT_0)
|
if (WaitForSingleObject(thread.second.get(), seconds * 100) != WAIT_OBJECT_0)
|
||||||
OSTerminateThread(thread.first.release(), 0);
|
OSTerminateThread(thread.first.release(), 0);
|
||||||
|
else
|
||||||
|
App->AddPendingStreamThread(thread.first.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void AddPacket(const BYTE *data, UINT size, DWORD timestamp, DWORD pts, PacketType type) override
|
virtual void AddPacket(const BYTE *data, UINT size, DWORD timestamp, DWORD pts, PacketType type) override
|
||||||
|
@ -369,7 +371,7 @@ struct RecordingHelper : VideoFileStream
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void CreateRecordingHelper(VideoFileStream *&stream, packet_list_t &packets)
|
void CreateRecordingHelper(unique_ptr<VideoFileStream> &stream, packet_list_t &packets)
|
||||||
{
|
{
|
||||||
if (stream)
|
if (stream)
|
||||||
{
|
{
|
||||||
|
@ -382,7 +384,7 @@ void CreateRecordingHelper(VideoFileStream *&stream, packet_list_t &packets)
|
||||||
|
|
||||||
auto helper = make_unique<RecordingHelper>(packet_vec_t{begin(packets), end(packets)});
|
auto helper = make_unique<RecordingHelper>(packet_vec_t{begin(packets), end(packets)});
|
||||||
if (helper->StartRecording())
|
if (helper->StartRecording())
|
||||||
stream = helper.release();
|
stream.reset(helper.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<ReplayBuffer*, unique_ptr<VideoFileStream>> CreateReplayBuffer(int seconds)
|
pair<ReplayBuffer*, unique_ptr<VideoFileStream>> CreateReplayBuffer(int seconds)
|
||||||
|
|
Loading…
Reference in New Issue