0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-20 04:42:18 +02:00

win-dshow: Allow synchronous create/update

Allows the ability to (optionally) synchronously create/update a
directshow device source rather than always asynchronously update the
device.  This is useful if creating/destroying scenes/sources very
quickly, and helps minimize the risk of creating new directshow sources
that use the same device, yet may not activate because an existing
source may already exist.  To use, set "synchronous_activate" to true in
its settings when updating or creating.  Note that this setting will be
erased after it's used, and will not be saved to user settings, so it
must be set each time in order to be used.

Closes obsproject/obs-studio#1228
This commit is contained in:
Ilya Melamed 2018-05-05 11:38:32 -07:00 committed by jp9000
parent e265fc92ed
commit db06a1c12a

View File

@ -150,6 +150,7 @@ public:
enum class Action {
None,
Activate,
ActivateBlock,
Deactivate,
Shutdown,
ConfigVideo,
@ -179,6 +180,7 @@ struct DShowInput {
obs_source_audio audio;
WinHandle semaphore;
WinHandle activated_event;
WinHandle thread;
CriticalSection mutex;
vector<Action> actions;
@ -190,6 +192,16 @@ struct DShowInput {
ReleaseSemaphore(semaphore, 1, nullptr);
}
inline void QueueActivate(obs_data_t *settings)
{
bool block = obs_data_get_bool(settings, "synchronous_activate");
QueueAction(block ? Action::ActivateBlock : Action::Activate);
if (block) {
obs_data_erase(settings, "synchronous_activate");
WaitForSingleObject(activated_event, INFINITE);
}
}
inline DShowInput(obs_source_t *source_, obs_data_t *settings)
: source (source_),
device (InitGraph::False)
@ -204,6 +216,10 @@ struct DShowInput {
if (!semaphore)
throw "Failed to create semaphore";
activated_event = CreateEvent(nullptr, false, false, nullptr);
if (!activated_event)
throw "Failed to create activated_event";
thread = CreateThread(nullptr, 0, DShowThread, this, 0,
nullptr);
if (!thread)
@ -215,7 +231,7 @@ struct DShowInput {
if (obs_data_get_bool(settings, "active")) {
bool showing = obs_source_showing(source);
if (!deactivateWhenNotShowing || showing)
QueueAction(Action::Activate);
QueueActivate(settings);
active = true;
}
@ -304,13 +320,18 @@ void DShowInput::DShowLoop()
switch (action) {
case Action::Activate:
case Action::ActivateBlock:
{
bool block = action == Action::ActivateBlock;
obs_data_t *settings;
settings = obs_source_get_settings(source);
if (!Activate(settings)) {
obs_source_output_video(source,
nullptr);
}
if (block)
SetEvent(activated_event);
obs_data_release(settings);
break;
}
@ -1075,9 +1096,7 @@ static void UpdateDShowInput(void *data, obs_data_t *settings)
{
DShowInput *input = reinterpret_cast<DShowInput*>(data);
if (input->active)
input->QueueAction(Action::Activate);
UNUSED_PARAMETER(settings);
input->QueueActivate(settings);
}
static void GetDShowDefaults(obs_data_t *settings)