CASPAR_LOG_CURRENT_EXCEPTION();\r
} \r
}\r
+ \r
+ void apply_transforms(const std::vector<std::tuple<int, stage::transform_func_t, unsigned int, std::wstring>>& transforms)\r
+ {\r
+ executor_.begin_invoke([=]\r
+ {\r
+ BOOST_FOREACH(auto& transform, transforms)\r
+ {\r
+ auto src = transforms_[std::get<0>(transform)].fetch();\r
+ auto dst = std::get<1>(transform)(src);\r
+ transforms_[std::get<0>(transform)] = tweened_transform<frame_transform>(src, dst, std::get<2>(transform), std::get<3>(transform));\r
+ }\r
+ }, high_priority);\r
+ }\r
\r
- void apply_transform(int index, const std::function<frame_transform(frame_transform)>& transform, unsigned int mix_duration, const std::wstring& tween)\r
+ void apply_transform(int index, const stage::transform_func_t& transform, unsigned int mix_duration, const std::wstring& tween)\r
{\r
executor_.begin_invoke([=]\r
{\r
};\r
\r
stage::stage(const safe_ptr<stage::target_t>& target, const safe_ptr<diagnostics::graph>& graph, const struct video_format_desc& format_desc) : impl_(new impl(target, graph, format_desc)){}\r
+void stage::apply_transforms(const std::vector<stage::transform_tuple_t>& transforms){impl_->apply_transforms(transforms);}\r
void stage::apply_transform(int index, const std::function<core::frame_transform(core::frame_transform)>& transform, unsigned int mix_duration, const std::wstring& tween){impl_->apply_transform(index, transform, mix_duration, tween);}\r
void stage::clear_transforms(int index){impl_->clear_transforms(index);}\r
void stage::clear_transforms(){impl_->clear_transforms();}\r
#include <boost/regex.hpp>\r
#include <boost/property_tree/xml_parser.hpp>\r
\r
+#include <tbb/concurrent_unordered_map.h>\r
+\r
/* Return codes\r
\r
100 [action] Information om att något har hänt \r
}\r
}\r
\r
+tbb::concurrent_unordered_map<int, std::vector<stage::transform_tuple_t>> deferred_transforms;\r
+\r
bool MixerCommand::DoExecute()\r
{ \r
//Perform loading of the clip\r
try\r
{ \r
+ bool defer = _parameters.back() == L"DEFER";\r
+ if(defer)\r
+ _parameters.pop_back();\r
+\r
+ std::vector<stage::transform_tuple_t> transforms;\r
+\r
if(_parameters[0] == L"KEYER" || _parameters[0] == L"IS_KEY")\r
{\r
bool value = boost::lexical_cast<int>(_parameters.at(1));\r
- auto transform = [=](frame_transform transform) -> frame_transform\r
+ transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
{\r
transform.is_key = value;\r
return transform; \r
- };\r
-\r
- int layer = GetLayerIndex();\r
- GetChannel()->stage()->apply_transform(GetLayerIndex(), transform);\r
+ }, 0, L"linear"));\r
}\r
else if(_parameters[0] == L"OPACITY")\r
{\r
\r
double value = boost::lexical_cast<double>(_parameters.at(1));\r
\r
- auto transform = [=](frame_transform transform) -> frame_transform\r
+ transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
{\r
transform.opacity = value;\r
return transform; \r
- };\r
-\r
- int layer = GetLayerIndex();\r
- GetChannel()->stage()->apply_transform(GetLayerIndex(), transform, duration, tween);\r
+ }, duration, tween));\r
}\r
else if(_parameters[0] == L"FILL" || _parameters[0] == L"FILL_RECT")\r
{\r
double x_s = boost::lexical_cast<double>(_parameters.at(3));\r
double y_s = boost::lexical_cast<double>(_parameters.at(4));\r
\r
- auto transform = [=](frame_transform transform) mutable -> frame_transform\r
+ transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) mutable -> frame_transform\r
{\r
transform.fill_translation[0] = x;\r
transform.fill_translation[1] = y;\r
transform.clip_scale[0] = x_s;\r
transform.clip_scale[1] = y_s;\r
return transform;\r
- };\r
- \r
- int layer = GetLayerIndex();\r
- GetChannel()->stage()->apply_transform(GetLayerIndex(), transform, duration, tween);\r
+ }, duration, tween));\r
}\r
else if(_parameters[0] == L"CLIP" || _parameters[0] == L"CLIP_RECT")\r
{\r
double x_s = boost::lexical_cast<double>(_parameters.at(3));\r
double y_s = boost::lexical_cast<double>(_parameters.at(4));\r
\r
- auto transform = [=](frame_transform transform) -> frame_transform\r
+ transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
{\r
transform.clip_translation[0] = x;\r
transform.clip_translation[1] = y;\r
transform.clip_scale[0] = x_s;\r
transform.clip_scale[1] = y_s;\r
return transform;\r
- };\r
- \r
- int layer = GetLayerIndex();\r
- GetChannel()->stage()->apply_transform(GetLayerIndex(), transform, duration, tween);\r
+ }, duration, tween));\r
}\r
else if(_parameters[0] == L"GRID")\r
{\r
for(int y = 0; y < n; ++y)\r
{\r
int index = x+y*n+1;\r
- auto transform = [=](frame_transform transform) -> frame_transform\r
+ transforms.push_back(stage::transform_tuple_t(index, [=](frame_transform transform) -> frame_transform\r
{ \r
transform.fill_translation[0] = x*delta;\r
transform.fill_translation[1] = y*delta;\r
transform.clip_scale[0] = delta;\r
transform.clip_scale[1] = delta; \r
return transform;\r
- };\r
- GetChannel()->stage()->apply_transform(index, transform, duration, tween);\r
+ }, duration, tween));\r
}\r
}\r
}\r
auto value = boost::lexical_cast<double>(_parameters.at(1));\r
int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
- auto transform = [=](frame_transform transform) -> frame_transform\r
+ auto transform = stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
{\r
transform.brightness = value;\r
return transform;\r
- };\r
- \r
- int layer = GetLayerIndex();\r
- GetChannel()->stage()->apply_transform(GetLayerIndex(), transform, duration, tween); \r
+ }, duration, tween);\r
}\r
else if(_parameters[0] == L"SATURATION")\r
{\r
auto value = boost::lexical_cast<double>(_parameters.at(1));\r
int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
- auto transform = [=](frame_transform transform) -> frame_transform\r
+ auto transform = stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
{\r
transform.saturation = value;\r
return transform;\r
- };\r
- \r
- int layer = GetLayerIndex();\r
- GetChannel()->stage()->apply_transform(GetLayerIndex(), transform, duration, tween); \r
+ }, duration, tween); \r
}\r
else if(_parameters[0] == L"CONTRAST")\r
{\r
auto value = boost::lexical_cast<double>(_parameters.at(1));\r
int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
- auto transform = [=](frame_transform transform) -> frame_transform\r
+ auto transform = stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
{\r
transform.contrast = value;\r
return transform;\r
- };\r
- \r
- int layer = GetLayerIndex();\r
- GetChannel()->stage()->apply_transform(GetLayerIndex(), transform, duration, tween); \r
+ }, duration, tween); \r
}\r
else if(_parameters[0] == L"LEVELS")\r
{\r
int duration = _parameters.size() > 6 ? boost::lexical_cast<int>(_parameters[6]) : 0;\r
std::wstring tween = _parameters.size() > 7 ? _parameters[7] : L"linear";\r
\r
- auto transform = [=](frame_transform transform) -> frame_transform\r
+ auto transform = stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
{\r
transform.levels = value;\r
return transform;\r
- };\r
- \r
- int layer = GetLayerIndex();\r
- GetChannel()->stage()->apply_transform(GetLayerIndex(), transform, duration, tween); \r
+ }, duration, tween);\r
}\r
else if(_parameters[0] == L"VOLUME")\r
{\r
std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
double value = boost::lexical_cast<double>(_parameters[1]);\r
\r
- auto transform = [=](frame_transform transform) -> frame_transform\r
+ auto transform = stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
{\r
transform.volume = value;\r
return transform;\r
- };\r
- \r
- int layer = GetLayerIndex();\r
- GetChannel()->stage()->apply_transform(GetLayerIndex(), transform, duration, tween);\r
+ }, duration, tween);\r
}\r
else if(_parameters[0] == L"CLEAR")\r
{\r
else\r
GetChannel()->stage()->clear_transforms(layer);\r
}\r
+ else if(_parameters[0] == L"COMMIT")\r
+ {\r
+ transforms = std::move(deferred_transforms[GetChannelIndex()]);\r
+ }\r
else\r
{\r
SetReplyString(TEXT("404 MIXER ERROR\r\n"));\r
return false;\r
}\r
+\r
+ if(defer)\r
+ {\r
+ auto& defer_tranforms = deferred_transforms[GetChannelIndex()];\r
+ defer_tranforms.insert(defer_tranforms.end(), transforms.begin(), transforms.end());\r
+ }\r
+ else\r
+ GetChannel()->stage()->apply_transforms(transforms);\r
\r
SetReplyString(TEXT("202 MIXER OK\r\n"));\r
\r