mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-07-31 00:07:29 -05:00
Add option to reduce video matching latency
This commit is contained in:
parent
b2585ae176
commit
75cdd3c80d
|
|
@ -151,6 +151,8 @@ AdvSceneSwitcher.condition.video.condition.object="contains object"
|
|||
AdvSceneSwitcher.condition.video.askFileAction="Do you want to use an existing file or create a screenshot of the currently selected source?"
|
||||
AdvSceneSwitcher.condition.video.askFileAction.file="Use existing file"
|
||||
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Create screenshot"
|
||||
AdvSceneSwitcher.condition.video.reduceLatency="Reduce matching latency"
|
||||
AdvSceneSwitcher.condition.video.reduceLatency.tooltip="Enabling will reduce the matching latency, but will slow down the condition checks of all macros overall."
|
||||
AdvSceneSwitcher.condition.video.usePatternForChangedCheck="Use pattern matching"
|
||||
AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip="This will allow you to control how much the image has to change for the condition to be true."
|
||||
AdvSceneSwitcher.condition.video.patternThreshold="Threshold: "
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ void MacroActionScreenshot::CustomScreenshot()
|
|||
{
|
||||
auto s = obs_weak_source_get_source(_source);
|
||||
_screenshot.~ScreenshotHelper();
|
||||
new (&_screenshot) ScreenshotHelper(s, true, _path);
|
||||
new (&_screenshot) ScreenshotHelper(s, false, 0, true, _path);
|
||||
obs_source_release(s);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,10 @@ bool MacroConditionVideo::CheckCondition()
|
|||
return _lastMatchResult;
|
||||
}
|
||||
|
||||
if (_blockUntilScreenshotDone) {
|
||||
GetScreenshot(true);
|
||||
}
|
||||
|
||||
if (_screenshotData.done) {
|
||||
match = Compare();
|
||||
_lastMatchResult = match;
|
||||
|
|
@ -94,7 +98,7 @@ bool MacroConditionVideo::CheckCondition()
|
|||
match = _lastMatchResult;
|
||||
}
|
||||
|
||||
if (_getNextScreenshot) {
|
||||
if (!_blockUntilScreenshotDone && _getNextScreenshot) {
|
||||
GetScreenshot();
|
||||
}
|
||||
return match;
|
||||
|
|
@ -106,6 +110,8 @@ bool MacroConditionVideo::Save(obs_data_t *obj)
|
|||
_video.Save(obj);
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
obs_data_set_string(obj, "filePath", _file.c_str());
|
||||
obs_data_set_bool(obj, "blockUntilScreenshotDone",
|
||||
_blockUntilScreenshotDone);
|
||||
obs_data_set_bool(obj, "usePatternForChangedCheck",
|
||||
_usePatternForChangedCheck);
|
||||
obs_data_set_double(obj, "threshold", _patternThreshold);
|
||||
|
|
@ -143,6 +149,8 @@ bool MacroConditionVideo::Load(obs_data_t *obj)
|
|||
_condition =
|
||||
static_cast<VideoCondition>(obs_data_get_int(obj, "condition"));
|
||||
_file = obs_data_get_string(obj, "filePath");
|
||||
_blockUntilScreenshotDone =
|
||||
obs_data_get_bool(obj, "blockUntilScreenshotDone");
|
||||
_usePatternForChangedCheck =
|
||||
obs_data_get_bool(obj, "usePatternForChangedCheck");
|
||||
_patternThreshold = obs_data_get_double(obj, "threshold");
|
||||
|
|
@ -186,11 +194,12 @@ std::string MacroConditionVideo::GetShortDesc()
|
|||
return _video.ToString();
|
||||
}
|
||||
|
||||
void MacroConditionVideo::GetScreenshot()
|
||||
void MacroConditionVideo::GetScreenshot(bool blocking)
|
||||
{
|
||||
auto source = obs_weak_source_get_source(_video.GetVideo());
|
||||
_screenshotData.~ScreenshotHelper();
|
||||
new (&_screenshotData) ScreenshotHelper(source);
|
||||
new (&_screenshotData)
|
||||
ScreenshotHelper(source, blocking, GetSwitcher()->interval);
|
||||
obs_source_release(source);
|
||||
_getNextScreenshot = false;
|
||||
}
|
||||
|
|
@ -287,6 +296,8 @@ MacroConditionVideoEdit::MacroConditionVideoEdit(
|
|||
: QWidget(parent),
|
||||
_videoSelection(new VideoSelectionWidget(this)),
|
||||
_condition(new QComboBox()),
|
||||
_reduceLatency(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.video.reduceLatency"))),
|
||||
_usePatternForChangedCheck(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.video.usePatternForChangedCheck"))),
|
||||
_imagePath(new FileSelection()),
|
||||
|
|
@ -326,6 +337,8 @@ MacroConditionVideoEdit::MacroConditionVideoEdit(
|
|||
"AdvSceneSwitcher.condition.video.showMatch"))),
|
||||
_previewDialog(this, entryData.get(), &GetSwitcher()->m)
|
||||
{
|
||||
_reduceLatency->setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.video.reduceLatency.tooltip"));
|
||||
_imagePath->Button()->disconnect();
|
||||
_usePatternForChangedCheck->setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.video.usePatternForChangedCheck.tooltip"));
|
||||
|
|
@ -341,6 +354,8 @@ MacroConditionVideoEdit::MacroConditionVideoEdit(
|
|||
SLOT(VideoSelectionChanged(const VideoSelection &)));
|
||||
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_reduceLatency, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(ReduceLatencyChanged(int)));
|
||||
QWidget::connect(_imagePath, SIGNAL(PathChanged(const QString &)), this,
|
||||
SLOT(ImagePathChanged(const QString &)));
|
||||
QWidget::connect(_imagePath->Button(), SIGNAL(clicked()), this,
|
||||
|
|
@ -383,6 +398,7 @@ MacroConditionVideoEdit::MacroConditionVideoEdit(
|
|||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{videoSources}}", _videoSelection},
|
||||
{"{{condition}}", _condition},
|
||||
{"{{reduceLatency}}", _reduceLatency},
|
||||
{"{{imagePath}}", _imagePath},
|
||||
{"{{minNeighbors}}", _minNeighbors},
|
||||
{"{{minSize}}", _minSize},
|
||||
|
|
@ -442,6 +458,7 @@ MacroConditionVideoEdit::MacroConditionVideoEdit(
|
|||
mainLayout->addLayout(_sizeLayout);
|
||||
mainLayout->addLayout(_throttleControlLayout);
|
||||
mainLayout->addLayout(_checkAreaControlLayout);
|
||||
mainLayout->addWidget(_reduceLatency);
|
||||
mainLayout->addLayout(showMatchLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
|
|
@ -635,6 +652,16 @@ void MacroConditionVideoEdit::PatternThresholdChanged(double value)
|
|||
_entryData->_patternThreshold = value;
|
||||
}
|
||||
|
||||
void MacroConditionVideoEdit::ReduceLatencyChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(GetSwitcher()->m);
|
||||
_entryData->_blockUntilScreenshotDone = value;
|
||||
}
|
||||
|
||||
void MacroConditionVideoEdit::UseAlphaAsMaskChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
|
|
@ -851,6 +878,7 @@ void MacroConditionVideoEdit::UpdateEntryData()
|
|||
|
||||
_videoSelection->SetVideoSelection(_entryData->_video);
|
||||
_condition->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
_reduceLatency->setChecked(_entryData->_blockUntilScreenshotDone);
|
||||
_imagePath->SetPath(QString::fromStdString(_entryData->_file));
|
||||
_usePatternForChangedCheck->setChecked(
|
||||
_entryData->_usePatternForChangedCheck);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public:
|
|||
{
|
||||
return std::make_shared<MacroConditionVideo>(m);
|
||||
}
|
||||
void GetScreenshot();
|
||||
void GetScreenshot(bool blocking = false);
|
||||
bool LoadImageFromFile();
|
||||
bool LoadModelData(std::string &path);
|
||||
std::string GetModelDataPath() { return _modelDataPath; }
|
||||
|
|
@ -49,6 +49,13 @@ public:
|
|||
VideoSelection _video;
|
||||
VideoCondition _condition = VideoCondition::MATCH;
|
||||
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
// Enabling this will reduce matching latency, but slow down the
|
||||
// the condition checks of all macros overall.
|
||||
//
|
||||
// If not set the screenshot will be gathered in one interval and
|
||||
// checked in the next one.
|
||||
// If set both operations will happen in the same interval.
|
||||
bool _blockUntilScreenshotDone = false;
|
||||
bool _useAlphaAsMask = false;
|
||||
bool _usePatternForChangedCheck = false;
|
||||
PatternMatchData _patternData;
|
||||
|
|
@ -107,8 +114,11 @@ public:
|
|||
private slots:
|
||||
void VideoSelectionChanged(const VideoSelection &);
|
||||
void ConditionChanged(int cond);
|
||||
void ReduceLatencyChanged(int value);
|
||||
|
||||
void ImagePathChanged(const QString &text);
|
||||
void ImageBrowseButtonClicked();
|
||||
|
||||
void UsePatternForChangedCheckChanged(int value);
|
||||
void PatternThresholdChanged(double);
|
||||
void UseAlphaAsMaskChanged(int value);
|
||||
|
|
@ -134,8 +144,11 @@ protected:
|
|||
VideoSelectionWidget *_videoSelection;
|
||||
QComboBox *_condition;
|
||||
|
||||
QCheckBox *_reduceLatency;
|
||||
|
||||
QCheckBox *_usePatternForChangedCheck;
|
||||
FileSelection *_imagePath;
|
||||
|
||||
ThresholdSlider *_patternThreshold;
|
||||
QCheckBox *_useAlphaAsMask;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,35 @@
|
|||
#include "screenshot-helper.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
static void ScreenshotTick(void *param, float);
|
||||
|
||||
ScreenshotHelper::ScreenshotHelper(obs_source_t *source, bool saveToFile,
|
||||
ScreenshotHelper::ScreenshotHelper(obs_source_t *source, bool blocking,
|
||||
int timeout, bool saveToFile,
|
||||
std::string path)
|
||||
: weakSource(OBSGetWeakRef(source)),
|
||||
_blocking(blocking),
|
||||
_saveToFile(saveToFile),
|
||||
_path(path)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
_initDone = true;
|
||||
obs_add_tick_callback(ScreenshotTick, this);
|
||||
if (_blocking) {
|
||||
auto res =
|
||||
_cv.wait_for(lock, std::chrono::milliseconds(timeout));
|
||||
if (res == std::cv_status::timeout) {
|
||||
if (source) {
|
||||
blog(LOG_WARNING,
|
||||
"Failed to get screenshot in time for source %s",
|
||||
obs_source_get_name(source));
|
||||
} else {
|
||||
blog(LOG_WARNING,
|
||||
"Failed to get screenshot in time");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScreenshotHelper::~ScreenshotHelper()
|
||||
|
|
@ -104,6 +123,8 @@ void ScreenshotHelper::MarkDone()
|
|||
{
|
||||
time = std::chrono::high_resolution_clock::now();
|
||||
done = true;
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
_cv.notify_all();
|
||||
}
|
||||
|
||||
void ScreenshotHelper::WriteToFile()
|
||||
|
|
@ -148,8 +169,8 @@ static void ScreenshotTick(void *param, float)
|
|||
break;
|
||||
case STAGE_COPY_AND_SAVE:
|
||||
data->Copy();
|
||||
data->MarkDone();
|
||||
data->WriteToFile();
|
||||
data->MarkDone();
|
||||
|
||||
obs_remove_tick_callback(ScreenshotTick, data);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -4,11 +4,14 @@
|
|||
#include <QImage>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
class ScreenshotHelper {
|
||||
public:
|
||||
ScreenshotHelper() = default;
|
||||
ScreenshotHelper(obs_source_t *source, bool saveToFile = false,
|
||||
ScreenshotHelper(obs_source_t *source, bool blocking = false,
|
||||
int timeout = 1000, bool saveToFile = false,
|
||||
std::string path = "");
|
||||
ScreenshotHelper &operator=(const ScreenshotHelper &) = delete;
|
||||
ScreenshotHelper(const ScreenshotHelper &) = delete;
|
||||
|
|
@ -34,7 +37,10 @@ public:
|
|||
|
||||
private:
|
||||
bool _initDone = false;
|
||||
bool _blocking = false;
|
||||
std::thread _saveThread;
|
||||
bool _saveToFile = false;
|
||||
std::string _path = "";
|
||||
std::mutex _mutex;
|
||||
std::condition_variable _cv;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user