]> git.sesse.net Git - casparcg/commitdiff
Added DEFER/COMMIT to MIXER commands for transform batching.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Thu, 12 Jan 2012 13:47:01 +0000 (13:47 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Thu, 12 Jan 2012 13:47:01 +0000 (13:47 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/trunk@2114 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

core/producer/stage.cpp
core/producer/stage.h
protocol/amcp/AMCPCommandsImpl.cpp

index e56a087a2c6e672a70033dc5e89b07aaa1da681e..65ae5e30f161159522f56a5436eb57f8582c753c 100644 (file)
@@ -176,8 +176,21 @@ public:
                        transforms_[index] = tweened_transform<frame_transform>(src, dst, mix_duration, tween);\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
+                                       \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 stage::transform_func_t& transform, unsigned int mix_duration, const std::wstring& tween)\r
        {\r
                executor_.begin_invoke([=]\r
                {\r
@@ -345,8 +358,8 @@ public:
 };\r
 \r
 stage::stage(const safe_ptr<diagnostics::graph>& graph, const safe_ptr<target_t>& target, const video_format_desc& format_desc) : impl_(new implementation(graph, target, format_desc)){}\r
-void stage::set_frame_transform(int index, const core::frame_transform& transform, unsigned int mix_duration, const std::wstring& tween){impl_->set_transform(index, transform, mix_duration, tween);}\r
-void stage::apply_frame_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::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
 void stage::spawn_token(){impl_->spawn_token();}\r
index e6b989fcc93e9376ab9dbf34b8b156a4df5fce7a..e7178caa0add511115b56203d36eef485860c7e7 100644 (file)
@@ -41,14 +41,16 @@ struct frame_transform;
 class stage : boost::noncopyable\r
 {\r
 public:\r
+       typedef std::function<struct frame_transform(struct frame_transform)>                                                   transform_func_t;\r
+       typedef std::tuple<int, transform_func_t, unsigned int, std::wstring>                                                   transform_tuple_t;\r
        typedef target<std::pair<std::map<int, safe_ptr<basic_frame>>, std::shared_ptr<void>>> target_t;\r
 \r
        explicit stage(const safe_ptr<diagnostics::graph>& graph, const safe_ptr<target_t>& target, const video_format_desc& format_desc);\r
        \r
        // stage\r
        \r
-       void set_frame_transform(int index, const frame_transform& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear");\r
-       void apply_frame_transform(int index, const std::function<frame_transform(frame_transform)>& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear");\r
+       void apply_transforms(const std::vector<transform_tuple_t>& transforms);\r
+       void apply_transform(int index, const transform_func_t& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear");\r
        void clear_transforms(int index);\r
        void clear_transforms();\r
 \r
index 4888b4f91a01bea937494a47c2859522f7576dd1..fbf21d48c21f3e63563784298295630adc61dbf3 100644 (file)
@@ -69,6 +69,8 @@
 #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
@@ -266,7 +268,7 @@ bool ChannelGridCommand::DoExecute()
                                transform.clip_scale[1]                 = delta;                        \r
                                return transform;\r
                        };\r
-                       self->stage()->apply_frame_transform(index, transform);\r
+                       self->stage()->apply_transform(index, transform);\r
                }\r
        }\r
 \r
@@ -317,49 +319,52 @@ bool CallCommand::DoExecute()
        }\r
 }\r
 \r
+// UGLY HACK\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 = lexical_cast_or_default(_parameters.at(1), false);\r
-                       auto transform = [=](frame_transform transform) -> frame_transform\r
+                       bool value = boost::lexical_cast<int>(_parameters.at(1));\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_frame_transform(GetLayerIndex(), transform);\r
+                       }, 0, L"linear"));\r
                }\r
                else if(_parameters[0] == L"OPACITY")\r
                {\r
-                       int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0;\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
 \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_frame_transform(GetLayerIndex(), transform, duration, tween);\r
+                       }, duration, tween));\r
                }\r
                else if(_parameters[0] == L"FILL" || _parameters[0] == L"FILL_RECT")\r
                {\r
-                       int duration = _parameters.size() > 5 ? lexical_cast_or_default(_parameters[5], 0) : 0;\r
+                       int duration = _parameters.size() > 5 ? boost::lexical_cast<int>(_parameters[5]) : 0;\r
                        std::wstring tween = _parameters.size() > 6 ? _parameters[6] : L"linear";\r
                        double x        = boost::lexical_cast<double>(_parameters.at(1));\r
                        double y        = boost::lexical_cast<double>(_parameters.at(2));\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
@@ -370,35 +375,29 @@ bool MixerCommand::DoExecute()
                                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_frame_transform(GetLayerIndex(), transform, duration, tween);\r
+                       }, duration, tween));\r
                }\r
                else if(_parameters[0] == L"CLIP" || _parameters[0] == L"CLIP_RECT")\r
                {\r
-                       int duration = _parameters.size() > 5 ? lexical_cast_or_default(_parameters[5], 0) : 0;\r
+                       int duration = _parameters.size() > 5 ? boost::lexical_cast<int>(_parameters[5]) : 0;\r
                        std::wstring tween = _parameters.size() > 6 ? _parameters[6] : L"linear";\r
                        double x        = boost::lexical_cast<double>(_parameters.at(1));\r
                        double y        = boost::lexical_cast<double>(_parameters.at(2));\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_frame_transform(GetLayerIndex(), transform, duration, tween);\r
+                       }, duration, tween));\r
                }\r
                else if(_parameters[0] == L"GRID")\r
                {\r
-                       int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0;\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
                        int n = boost::lexical_cast<int>(_parameters.at(1));\r
                        double delta = 1.0/static_cast<double>(n);\r
@@ -407,7 +406,7 @@ bool MixerCommand::DoExecute()
                                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
@@ -418,8 +417,7 @@ bool MixerCommand::DoExecute()
                                                transform.clip_scale[0]                 = delta;\r
                                                transform.clip_scale[1]                 = delta;                        \r
                                                return transform;\r
-                                       };\r
-                                       GetChannel()->stage()->apply_frame_transform(index, transform, duration, tween);\r
+                                       }, duration, tween));\r
                                }\r
                        }\r
                }\r
@@ -432,44 +430,35 @@ bool MixerCommand::DoExecute()
                else if(_parameters[0] == L"BRIGHTNESS")\r
                {\r
                        auto value = boost::lexical_cast<double>(_parameters.at(1));\r
-                       int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0;\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_frame_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 ? lexical_cast_or_default(_parameters[2], 0) : 0;\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_frame_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 ? lexical_cast_or_default(_parameters[2], 0) : 0;\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_frame_transform(GetLayerIndex(), transform, duration, tween);      \r
+                       }, duration, tween);    \r
                }\r
                else if(_parameters[0] == L"LEVELS")\r
                {\r
@@ -479,32 +468,26 @@ bool MixerCommand::DoExecute()
                        value.gamma              = boost::lexical_cast<double>(_parameters.at(3));\r
                        value.min_output = boost::lexical_cast<double>(_parameters.at(4));\r
                        value.max_output = boost::lexical_cast<double>(_parameters.at(5));\r
-                       int duration = _parameters.size() > 6 ? lexical_cast_or_default(_parameters[6], 0) : 0;\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_frame_transform(GetLayerIndex(), transform, duration, tween);      \r
+                       }, duration, tween);\r
                }\r
                else if(_parameters[0] == L"VOLUME")\r
                {\r
-                       int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0;\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
                        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_frame_transform(GetLayerIndex(), transform, duration, tween);\r
+                       }, duration, tween);\r
                }\r
                else if(_parameters[0] == L"CLEAR")\r
                {\r
@@ -514,11 +497,23 @@ bool MixerCommand::DoExecute()
                        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