From 8919fcb31d79e73ab139991a107ae18c1fde9740 Mon Sep 17 00:00:00 2001 From: palana Date: Tue, 16 Sep 2014 17:06:18 +0200 Subject: [PATCH] Add ClosableStream interface and pending stream helpers --- Source/OBS.cpp | 2 ++ Source/OBS.h | 20 ++++++++++++++++ Source/OBSCapture.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++ rundir/locale/en.txt | 1 + 4 files changed, 79 insertions(+) diff --git a/Source/OBS.cpp b/Source/OBS.cpp index 6abf062d8..7da09e7be 100644 --- a/Source/OBS.cpp +++ b/Source/OBS.cpp @@ -823,6 +823,8 @@ OBS::~OBS() OSTerminateThread(hHotkeyThread, 2500); + ClosePendingStreams(); + for(UINT i=0; i +#include #pragma once @@ -86,6 +87,13 @@ bool GetDefaultSpeakerID(String &strVal); //------------------------------------------------------------------- +struct ClosableStream +{ + virtual ~ClosableStream() {} +}; + +//------------------------------------------------------------------- + struct DataPacket { LPBYTE lpPacket; @@ -1263,6 +1271,18 @@ class OBS inline void ResetMic() {if (bRunning && micAudio) ResetWASAPIAudioDevice(micAudio);} void GetThreadHandles (HANDLE *videoThread, HANDLE *encodeThread); + + struct PendingStreams + { + using thread_t = std::unique_ptr>; + std::list streams; + std::unique_ptr mutex; + PendingStreams() : mutex(OSCreateMutex()) {} + } pendingStreams; + + void AddPendingStream(ClosableStream *stream, std::function finishedCallback = {}); + void AddPendingStreamThread(HANDLE thread); + void ClosePendingStreams(); }; LONG CALLBACK OBSExceptionHandler (PEXCEPTION_POINTERS exceptionInfo); diff --git a/Source/OBSCapture.cpp b/Source/OBSCapture.cpp index 8a040cadd..e92a155b5 100644 --- a/Source/OBSCapture.cpp +++ b/Source/OBSCapture.cpp @@ -1509,5 +1509,61 @@ void OBS::RequestKeyframe(int waitTime) keyframeWait = waitTime; } +void OBS::AddPendingStream(ClosableStream *stream, std::function finishedCallback) +{ + using namespace std; + struct args_t + { + using stream_t = remove_pointer_t; + unique_ptr stream; + decltype(finishedCallback) finishedCallback; + args_t(stream_t *stream, decltype(finishedCallback) finishedCallback) : stream(stream), finishedCallback(move(finishedCallback)) {} + }; + + auto args = make_unique(stream, move(finishedCallback)); + + ScopedLock l(pendingStreams.mutex); + pendingStreams.streams.emplace_back(OSCreateThread([](void *arg) -> DWORD + { + unique_ptr args(static_cast(arg)); + args->stream.reset(); + if (args->finishedCallback) + args->finishedCallback(); + return 0; + }, args.release())); +} +void OBS::AddPendingStreamThread(HANDLE thread) +{ + ScopedLock l(pendingStreams.mutex); + pendingStreams.streams.emplace_back(thread); +} + +void OBS::ClosePendingStreams() +{ + ScopedLock l(pendingStreams.mutex); + if (pendingStreams.streams.empty()) + return; + using namespace std; + vector handles; + for (auto &pendingStream : pendingStreams.streams) + handles.push_back(pendingStream.get()); + + if (WaitForMultipleObjects(handles.size(), handles.data(), true, 5) != WAIT_OBJECT_0) + { + using ::locale; + int res = IDNO; + do + { + auto res = OBSMessageBox(hwndMain, Str("StreamClosePending"), nullptr, MB_YESNO | MB_ICONEXCLAMATION); + + if (res != IDYES) + return; + + if (WaitForMultipleObjects(handles.size(), handles.data(), true, 15 * 1000) == WAIT_OBJECT_0) + return; + + } while (res == IDYES); + } +} diff --git a/rundir/locale/en.txt b/rundir/locale/en.txt index 4eb26871d..da99bdd4a 100644 --- a/rundir/locale/en.txt +++ b/rundir/locale/en.txt @@ -43,6 +43,7 @@ LogWindow="Log Window" StreamReport="Stream Report" MessageBoxWarningCaption="Warning" NoSourcesFound="You haven't added any sources! Are you sure you want to stream a black screen?" +StreamClosePending="Stream or file output unfinished, closing OBS may cause the stream to end prematurely or the file to be corrupted. Do you want to wait another 15 seconds for the output to finish?" ImportGlobalSourceNameExists="The global source '$1' already exists in the current scene collection." ImportGlobalSources="Import Global Sources"