]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2: Improved mixer transform interface. Removed animated transforms, for now.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Thu, 3 Mar 2011 15:31:12 +0000 (15:31 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Thu, 3 Mar 2011 15:31:12 +0000 (15:31 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@516 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

mixer/frame_mixer_device.cpp
mixer/frame_mixer_device.h
protocol/amcp/AMCPCommandsImpl.cpp

index 070ead69bf811533af2e85f886eec3cc3de5e044..6a5f107e99530ca9cca7150d1a1d7ae97ad67001 100644 (file)
 #include <unordered_map>\r
 \r
 namespace caspar { namespace core {\r
-\r
-template<typename T>\r
-struct animated_value\r
-{\r
-       virtual T fetch() = 0;\r
-       virtual T fetch_and_tick(bool& done) = 0;\r
-       T fetch_and_tick()\r
-       {\r
-               bool dummy;\r
-               return fetch_and_tick(dummy);\r
-       }\r
-\r
-       virtual safe_ptr<animated_value<T>> source() = 0;\r
-       virtual safe_ptr<animated_value<T>> dest() = 0;\r
-};\r
-\r
-template<typename T>\r
-class basic_animated_value : public animated_value<T>\r
-{\r
-       T current_;\r
-public:\r
-       basic_animated_value(){}\r
-       basic_animated_value(const T& current) : current_(current){}\r
        \r
-       virtual T fetch(){return current_;}\r
-       virtual T fetch_and_tick(bool& done)\r
-       {\r
-               done = false;\r
-               return current_;\r
-       }\r
-\r
-       virtual safe_ptr<animated_value<T>> source() {return make_safe<basic_animated_value<T>>(current_);}\r
-       virtual safe_ptr<animated_value<T>> dest() {return make_safe<basic_animated_value<T>>(current_);}\r
-};\r
-       \r
-template<typename T>\r
-class nested_animated_value : public animated_value<T>\r
-{\r
-       safe_ptr<animated_value<T>> source_;\r
-       safe_ptr<animated_value<T>> dest_;\r
-       const int duration_;\r
-       int time_;\r
-public:\r
-       nested_animated_value()\r
-               : source_(basic_animated_value<T>())\r
-               , dest_(basic_animated_value<T>())\r
-               , duration_(duration)\r
-               , time_(0){}\r
-       nested_animated_value(const safe_ptr<animated_value<T>>& source, const safe_ptr<animated_value<T>>& dest, int duration)\r
-               : source_(source)\r
-               , dest_(dest)\r
-               , duration_(duration)\r
-               , time_(0){}\r
-       \r
-       virtual T fetch()\r
-       {\r
-               return lerp(source_->fetch(), dest_->fetch(), duration_ < 1 ? 1.0f : static_cast<float>(time_)/static_cast<float>(duration_));\r
-       }\r
-       virtual T fetch_and_tick(bool& done)\r
-       {\r
-               done = time_ >= duration_;\r
-\r
-               bool src_done = false;\r
-               auto src = source_->fetch_and_tick(src_done);\r
-               if(src_done)\r
-                       source_ = source_->dest();\r
-               \r
-               bool dst_done = false;\r
-               auto dst = dest_->fetch_and_tick(dst_done);\r
-               if(dst_done)\r
-                       dest_ = dest_->dest();\r
-                                               \r
-               time_ = std::min(time_+1, duration_);\r
-               return lerp(src, dst, duration_ < 1 ? 1.0f : (static_cast<float>(time_)/static_cast<float>(duration_)));\r
-       }\r
-\r
-       virtual safe_ptr<animated_value<T>> source() {return source_;}\r
-       virtual safe_ptr<animated_value<T>> dest() {return dest_;}\r
-};\r
-\r
 struct frame_mixer_device::implementation : boost::noncopyable\r
 {              \r
        const printer                   parent_printer_;\r
@@ -124,7 +45,7 @@ struct frame_mixer_device::implementation : boost::noncopyable
        std::unordered_map<int, audio_transform> audio_transforms_;\r
 \r
        image_transform root_image_transform_;\r
-       safe_ptr<animated_value<audio_transform>> root_audio_transform_;\r
+       audio_transform root_audio_transform_;\r
 \r
        executor executor_;\r
 public:\r
@@ -135,7 +56,6 @@ public:
                , image_mixer_(format_desc)\r
                , output_(output)\r
                , executor_(print())\r
-               , root_audio_transform_(basic_animated_value<audio_transform>())\r
        {\r
                graph_->guide("frame-time", 0.5f);      \r
                graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
@@ -163,7 +83,7 @@ public:
                        auto audio = audio_mixer_.begin_pass();\r
                        BOOST_FOREACH(auto& frame, frames)\r
                        {\r
-                               audio_mixer_.begin(root_audio_transform_->fetch_and_tick()*audio_transforms_[frame->get_layer_index()]);\r
+                               audio_mixer_.begin(root_audio_transform_*audio_transforms_[frame->get_layer_index()]);\r
                                frame->process_audio(audio_mixer_);\r
                                audio_mixer_.end();\r
                        }\r
@@ -184,46 +104,68 @@ public:
        {\r
                return make_safe<write_frame>(desc, image_mixer_.create_buffers(desc));\r
        }\r
-               \r
-       image_transform get_image_transform(int index)\r
+                               \r
+       void set_image_transform(const image_transform& transform, int)\r
+       {\r
+               executor_.invoke([&]\r
+               {\r
+                       root_image_transform_ = transform;\r
+               });\r
+       }\r
+\r
+       void set_audio_transform(const audio_transform& transform, int)\r
+       {\r
+               executor_.invoke([&]\r
+               {\r
+                       root_audio_transform_ = transform;\r
+               });\r
+       }\r
+\r
+       void set_image_transform(int index, const image_transform& transform, int)\r
        {\r
-               return executor_.invoke([&]{return image_transforms_[index];});\r
+               executor_.invoke([&]\r
+               {\r
+                       image_transforms_[index] = transform;\r
+               });\r
        }\r
 \r
-       audio_transform get_audio_transform(int index)\r
+       void set_audio_transform(int index, const audio_transform& transform, int)\r
        {\r
-               return executor_.invoke([&]{return audio_transforms_[index];});\r
+               executor_.invoke([&]\r
+               {\r
+                       audio_transforms_[index] = transform;\r
+               });\r
        }\r
        \r
-       void set_image_transform(const image_transform& transform, int mix_duration)\r
+       void apply_image_transform(const std::function<image_transform(const image_transform&)> transform, int)\r
        {\r
                return executor_.invoke([&]\r
                {\r
-                       root_image_transform_ = root_image_transform_;\r
+                       root_image_transform_ = transform(root_image_transform_);\r
                });\r
        }\r
 \r
-       void set_audio_transform(const audio_transform& transform, int mix_duration)\r
+       void apply_audio_transform(const std::function<audio_transform(audio_transform)> transform, int)\r
        {\r
                return executor_.invoke([&]\r
                {\r
-                       root_audio_transform_ = make_safe<nested_animated_value<audio_transform>>(root_audio_transform_, make_safe<basic_animated_value<audio_transform>>(transform), mix_duration);\r
+                       root_audio_transform_ = transform(root_audio_transform_);\r
                });\r
        }\r
 \r
-       void set_image_transform(int index, const image_transform& transform, int mix_duration)\r
+       void apply_image_transform(int index, const std::function<image_transform(image_transform)> transform, int)\r
        {\r
-               return executor_.invoke([&]\r
+               executor_.invoke([&]\r
                {\r
-                       image_transforms_[index] = transform;\r
+                       image_transforms_[index] = transform(image_transforms_[index]);\r
                });\r
        }\r
 \r
-       void set_audio_transform(int index, const audio_transform& transform, int mix_duration)\r
+       void apply_audio_transform(int index, const std::function<audio_transform(audio_transform)> transform, int)\r
        {\r
-               return executor_.invoke([&]\r
+               executor_.invoke([&]\r
                {\r
-                       audio_transforms_[index] = transform;\r
+                       audio_transforms_[index] = transform(audio_transforms_[index]);\r
                });\r
        }\r
 \r
@@ -255,11 +197,13 @@ safe_ptr<write_frame> frame_mixer_device::create_frame(pixel_format::type pix_fm
        desc.planes.push_back(pixel_format_desc::plane(get_video_format_desc().width, get_video_format_desc().height, 4));\r
        return create_frame(desc);\r
 }\r
-image_transform frame_mixer_device::get_image_transform(int index){return impl_->get_image_transform(index);}\r
-audio_transform frame_mixer_device::get_audio_transform(int index){return impl_->get_audio_transform(index);}\r
 void frame_mixer_device::set_image_transform(const image_transform& transform, int mix_duration){impl_->set_image_transform(transform, mix_duration);}\r
-void frame_mixer_device::set_audio_transform(const audio_transform& transform, int mix_duration){impl_->set_audio_transform(transform, mix_duration);}\r
 void frame_mixer_device::set_image_transform(int index, const image_transform& transform, int mix_duration){impl_->set_image_transform(index, transform, mix_duration);}\r
+void frame_mixer_device::set_audio_transform(const audio_transform& transform, int mix_duration){impl_->set_audio_transform(transform, mix_duration);}\r
 void frame_mixer_device::set_audio_transform(int index, const audio_transform& transform, int mix_duration){impl_->set_audio_transform(index, transform, mix_duration);}\r
+void frame_mixer_device::apply_image_transform(const std::function<image_transform(image_transform)>& transform, int mix_duration ){impl_->apply_image_transform(transform, mix_duration);}\r
+void frame_mixer_device::apply_image_transform(int index, const std::function<image_transform(image_transform)>& transform, int mix_duration){impl_->apply_image_transform(index, transform, mix_duration);}\r
+void frame_mixer_device::apply_audio_transform(const std::function<audio_transform(audio_transform)>& transform, int mix_duration){impl_->apply_audio_transform(transform, mix_duration);}\r
+void frame_mixer_device::apply_audio_transform(int index, const std::function<audio_transform(audio_transform)>& transform, int mix_duration ){impl_->apply_audio_transform(index, transform, mix_duration);}\r
 \r
 }}
\ No newline at end of file
index e462f633b6cd6cb0474bb03d9ffbfbd2fa7bda3e..5b1a43e847d069cf413e348dba67544f35b25470 100644 (file)
@@ -54,13 +54,17 @@ public:
        \r
        const video_format_desc& get_video_format_desc() const; // nothrow\r
 \r
-       image_transform get_image_transform(int index);\r
-       audio_transform get_audio_transform(int index);\r
-       \r
        void set_image_transform(const image_transform& transform, int mix_duration = 0);\r
-       void set_audio_transform(const audio_transform& transform, int mix_duration = 0);\r
        void set_image_transform(int index, const image_transform& transform, int mix_duration = 0);\r
+\r
+       void set_audio_transform(const audio_transform& transform, int mix_duration = 0);\r
        void set_audio_transform(int index, const audio_transform& transform, int mix_duration = 0);\r
+       \r
+       void apply_image_transform(const std::function<image_transform(image_transform)>& transform, int mix_duration = 0);\r
+       void apply_image_transform(int index, const std::function<image_transform(image_transform)>& transform, int mix_duration = 0);\r
+\r
+       void apply_audio_transform(const std::function<audio_transform(audio_transform)>& transform, int mix_duration = 0);\r
+       void apply_audio_transform(int index, const std::function<audio_transform(audio_transform)>& transform, int mix_duration = 0);\r
 \r
 private:\r
        struct implementation;\r
index c51ae7738b333ee1267927a338a63357998472a9..c059a9641e128f94ce8d997fe1e3f1751381004b 100644 (file)
@@ -181,27 +181,35 @@ bool MixerCommand::DoExecute()
                        {\r
                                int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0;\r
                                double value = boost::lexical_cast<double>(_parameters.at(2));\r
-                               auto transform = GetChannel()->mixer().get_image_transform(GetLayerIndex());\r
-                               transform.set_opacity(value);\r
+                       \r
+                               auto transform = [=](image_transform transform) -> image_transform\r
+                               {\r
+                                       transform.set_opacity(value);\r
+                                       return transform;                                       \r
+                               };\r
 \r
                                int layer = GetLayerIndex(std::numeric_limits<int>::min());\r
                                if(layer != std::numeric_limits<int>::min())                                    \r
-                                       GetChannel()->mixer().set_image_transform(GetLayerIndex(), transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration);\r
                                else\r
-                                       GetChannel()->mixer().set_image_transform(transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(transform, duration);\r
                        }\r
                        else if(_parameters[1] == L"GAIN")\r
                        {\r
                                int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0;\r
                                double value = boost::lexical_cast<double>(_parameters.at(2));\r
-                               auto transform = GetChannel()->mixer().get_image_transform(GetLayerIndex());\r
-                               transform.set_gain(value);\r
+                               \r
+                               auto transform = [=](image_transform transform) -> image_transform\r
+                               {\r
+                                       transform.set_gain(value);\r
+                                       return transform;                                       \r
+                               };\r
 \r
                                int layer = GetLayerIndex(std::numeric_limits<int>::min());\r
                                if(layer != std::numeric_limits<int>::min())\r
-                                       GetChannel()->mixer().set_image_transform(GetLayerIndex(), transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration);\r
                                else\r
-                                       GetChannel()->mixer().set_image_transform(GetLayerIndex(), transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(transform, duration);\r
                        }\r
                        else if(_parameters[1] == L"FILL_RECT")\r
                        {\r
@@ -210,17 +218,21 @@ bool MixerCommand::DoExecute()
                                double y        = boost::lexical_cast<double>(_parameters.at(3));\r
                                double x_s      = boost::lexical_cast<double>(_parameters.at(4));\r
                                double y_s      = boost::lexical_cast<double>(_parameters.at(5));\r
-                               auto transform = GetChannel()->mixer().get_image_transform(GetLayerIndex());\r
-                               transform.set_fill_translation(x, y);\r
-                               transform.set_fill_scale(x_s, y_s);\r
-                               transform.set_key_translation(x, y);\r
-                               transform.set_key_scale(x_s, y_s);\r
+\r
+                               auto transform = [=](image_transform transform) -> image_transform\r
+                               {\r
+                                       transform.set_fill_translation(x, y);\r
+                                       transform.set_fill_scale(x_s, y_s);\r
+                                       transform.set_key_translation(x, y);\r
+                                       transform.set_key_scale(x_s, y_s);\r
+                                       return transform;\r
+                               };\r
 \r
                                int layer = GetLayerIndex(std::numeric_limits<int>::min());\r
                                if(layer != std::numeric_limits<int>::min())\r
-                                       GetChannel()->mixer().set_image_transform(GetLayerIndex(), transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration);\r
                                else\r
-                                       GetChannel()->mixer().set_image_transform(transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(transform, duration);\r
                        }\r
                        else if(_parameters[1] == L"KEY_RECT")\r
                        {\r
@@ -229,17 +241,21 @@ bool MixerCommand::DoExecute()
                                double y        = boost::lexical_cast<double>(_parameters.at(3));\r
                                double x_s      = boost::lexical_cast<double>(_parameters.at(4));\r
                                double y_s      = boost::lexical_cast<double>(_parameters.at(5));\r
-                               auto transform = GetChannel()->mixer().get_image_transform(GetLayerIndex());\r
-                               transform.set_fill_translation(0.0, 0.0);\r
-                               transform.set_fill_scale(1.0, 1.0);\r
-                               transform.set_key_translation(x, y);\r
-                               transform.set_key_scale(x_s, y_s);\r
+\r
+                               auto transform = [=](image_transform transform) -> image_transform\r
+                               {\r
+                                       transform.set_fill_translation(0.0, 0.0);\r
+                                       transform.set_fill_scale(1.0, 1.0);\r
+                                       transform.set_key_translation(x, y);\r
+                                       transform.set_key_scale(x_s, y_s);\r
+                                       return transform;\r
+                               };\r
 \r
                                int layer = GetLayerIndex(std::numeric_limits<int>::min());\r
                                if(layer != std::numeric_limits<int>::min())\r
-                                       GetChannel()->mixer().set_image_transform(GetLayerIndex(), transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration);\r
                                else\r
-                                       GetChannel()->mixer().set_image_transform(transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(transform, duration);\r
                        }\r
                        else if(_parameters[1] == L"GRID")\r
                        {\r
@@ -250,12 +266,15 @@ bool MixerCommand::DoExecute()
                                        for(int y = 0; y < n; ++y)\r
                                        {\r
                                                int index = x+y*n;\r
-                                               auto transform = GetChannel()->mixer().get_image_transform(index);                                              \r
-                                               transform.set_fill_translation(x*delta, y*delta);\r
-                                               transform.set_fill_scale(delta, delta);                 \r
-                                               transform.set_key_translation(x*delta, y*delta);\r
-                                               transform.set_key_scale(delta, delta);\r
-                                               GetChannel()->mixer().set_image_transform(index, transform, 0);\r
+                                               auto transform = [=](image_transform transform) -> image_transform\r
+                                               {                               \r
+                                                       transform.set_fill_translation(x*delta, y*delta);\r
+                                                       transform.set_fill_scale(delta, delta);                 \r
+                                                       transform.set_key_translation(x*delta, y*delta);\r
+                                                       transform.set_key_scale(delta, delta);\r
+                                                       return transform;\r
+                                               };\r
+                                               GetChannel()->mixer().apply_image_transform(index, transform, 0);\r
                                        }\r
                                }\r
                        }\r
@@ -270,14 +289,18 @@ bool MixerCommand::DoExecute()
                        {\r
                                int duration = _parameters.size() > 3 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
                                double value = boost::lexical_cast<double>(_parameters[2]);\r
-                               auto transform = GetChannel()->mixer().get_audio_transform(GetLayerIndex());\r
-                               transform.set_gain(value);\r
 \r
+                               auto transform = [=](audio_transform transform) -> audio_transform\r
+                               {\r
+                                       transform.set_gain(value);\r
+                                       return transform;\r
+                               };\r
+                               \r
                                int layer = GetLayerIndex(std::numeric_limits<int>::min());\r
                                if(layer != std::numeric_limits<int>::min())\r
-                                       GetChannel()->mixer().set_audio_transform(GetLayerIndex(), transform, duration);\r
+                                       GetChannel()->mixer().apply_audio_transform(GetLayerIndex(), transform, duration);\r
                                else\r
-                                       GetChannel()->mixer().set_audio_transform(transform, duration);\r
+                                       GetChannel()->mixer().apply_audio_transform(transform, duration);\r
                        }\r
                        else if(_parameters[1] == L"RESET")\r
                        {\r