]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2: amcp: Changed IS_KEY to KEY_DEPTH which is able to key several layers. Fixed...
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Mon, 16 May 2011 16:30:30 +0000 (16:30 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Mon, 16 May 2011 16:30:30 +0000 (16:30 +0000)
         mixer: Added support for key_depth.

git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@760 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

Casparcg 2.0 Documentation.txt
core/mixer/image/image_mixer.cpp
core/producer/frame/basic_frame.cpp
core/producer/frame/image_transform.cpp
core/producer/frame/image_transform.h
protocol/amcp/AMCPCommandsImpl.cpp
shell/caspar.config

index 46f0ee6a42a4cfae6a5c0cfafa24f28d7c6c68a1..a6d616fced30b338d5779b918056662acbc5c516 100644 (file)
@@ -632,20 +632,20 @@ Description:
 **********************************************************************************\r
 \r
 ----------------------------------------------------------------------------------\r
-2.7.1. MIXER VIDEO IS_KEY\r
+2.7.1. MIXER VIDEO KEY_DEPTH\r
 ----------------------------------------------------------------------------------\r
 Syntax: \r
 \r
-       MIXER [channel:int]{-[layer:int]|-0} VIDEO IS_KEY {is_key:0,1|0}\r
+       MIXER [channel:int]{-[layer:int]|-0} VIDEO KEY_DEPTH [key_depth:uint]\r
 \r
 Description: \r
 \r
-       If "is_key" equals 1 then the specified layer will not be rendered, \r
-       instead it will be used as the key for the layer above.\r
+       If "key_depth" is greater than 0 then the specified layer will not be rendered, \r
+       instead it will be used as the key for the "key_depth" number of layers above.\r
        \r
 Examples:      \r
 \r
-       >> MIXER VIDEO 1-0 IS_KEY 1\r
+       >> MIXER VIDEO 1-0 KEY_DEPTH 2\r
        \r
 Note:\r
 \r
index 660903063d923d5bded5ecfb060efcbd9c6223bd..87631e75b5260aab09b48fe7864b8a87f24daecc 100644 (file)
@@ -58,7 +58,12 @@ struct image_mixer::implementation : boost::noncopyable
 \r
        image_kernel kernel_;\r
 \r
-       std::shared_ptr<device_buffer> key_;\r
+       struct keyer\r
+       {\r
+               std::shared_ptr<device_buffer> key;\r
+               size_t depth;\r
+       } keyer_;\r
+\r
 public:\r
        implementation(const core::video_format_desc& format_desc) \r
                : format_desc_(format_desc)\r
@@ -100,48 +105,56 @@ public:
                \r
        void visit(core::write_frame& frame)\r
        {\r
-               auto gpu_frame = boost::polymorphic_downcast<gpu_write_frame*>(&frame);\r
-               auto desc = gpu_frame->get_pixel_format_desc();\r
-               auto buffers = gpu_frame->get_plane_buffers();\r
+               auto gpu_frame = dynamic_cast<gpu_write_frame*>(&frame);\r
+               if(!gpu_frame)\r
+                       return;\r
+\r
+               auto desc               = gpu_frame->get_pixel_format_desc();\r
+               auto buffers    = gpu_frame->get_plane_buffers();\r
+               auto transform  = transform_stack_.top();\r
+               \r
+               if(buffers.empty())             \r
+                       return;\r
 \r
-               auto transform = transform_stack_.top();\r
                ogl_device::begin_invoke([=]\r
-               {\r
-                       std::vector<safe_ptr<device_buffer>> device_buffers;\r
-                       for(size_t n = 0; n < buffers.size(); ++n)\r
+               {                                                               \r
+                       if(transform.get_key_depth() > 0) // Its a key_frame just save buffer for next frame.\r
                        {\r
-                               auto texture = ogl_device::create_device_buffer(desc.planes[n].width, desc.planes[n].height, desc.planes[n].channels);\r
-                               texture->read(*buffers[n]);\r
-                               device_buffers.push_back(texture);\r
-                       }\r
-                                               \r
-                       if(transform.get_is_key()) // Its a key_frame just save buffer for next frame.\r
-                       {\r
-                               if(!device_buffers.empty())                             \r
-                                       key_ = device_buffers[0];                               \r
+                               auto texture = create_device_buffer(desc.planes[0]);\r
+                               texture->read(*buffers[0]);\r
+                               keyer_.key = texture;\r
+                               keyer_.depth = transform.get_key_depth();                                               \r
                        }\r
                        else\r
-                       {\r
-                               for(size_t n = 0; n < buffers.size(); ++n)\r
+                       {                               \r
+                               const bool   has_separate_key = keyer_.depth > 0;\r
+                               const size_t max_index            = has_separate_key ? 3 : 4;\r
+                               \r
+                               std::vector<safe_ptr<device_buffer>> device_buffers;\r
+                               for(size_t n = 0; n < std::min(max_index, buffers.size()); ++n)\r
+                               {\r
+                                       auto texture = create_device_buffer(desc.planes[n]);\r
+                                       texture->read(*buffers[n]);\r
+                                       device_buffers.push_back(texture);\r
+                               }       \r
+\r
+                               if(has_separate_key && keyer_.key)\r
+                                       device_buffers.push_back(make_safe(keyer_.key));\r
+\r
+                               for(size_t n = 0; n < device_buffers.size(); ++n)\r
                                {\r
                                        GL(glActiveTexture(GL_TEXTURE0+n));\r
                                        device_buffers[n]->bind();\r
                                }\r
                                                \r
-                               if(key_)\r
-                               {\r
-                                       GL(glActiveTexture(GL_TEXTURE0+3));\r
-                                       key_->bind();\r
-                               }\r
-\r
                                GL(glColor4d(1.0, 1.0, 1.0, transform.get_opacity()));\r
                                GL(glViewport(0, 0, format_desc_.width, format_desc_.height));\r
-                               kernel_.apply(desc, transform, key_ != nullptr);\r
+                               kernel_.apply(desc, transform, has_separate_key);\r
                                                \r
                                auto m_p = transform.get_key_translation();\r
                                auto m_s = transform.get_key_scale();\r
-                               double w = static_cast<double>(format_desc_.width);\r
-                               double h = static_cast<double>(format_desc_.height);\r
+                               auto w   = static_cast<double>(format_desc_.width);\r
+                               auto h   = static_cast<double>(format_desc_.height);\r
                        \r
                                GL(glEnable(GL_SCISSOR_TEST));\r
                                GL(glScissor(static_cast<size_t>(m_p[0]*w), static_cast<size_t>(m_p[1]*h), static_cast<size_t>(m_s[0]*w), static_cast<size_t>(m_s[1]*h)));\r
@@ -157,7 +170,10 @@ public:
                                glEnd();\r
                                GL(glDisable(GL_SCISSOR_TEST));         \r
 \r
-                               key_ = nullptr;         \r
+                               if(keyer_.depth == 0)\r
+                                       keyer_.key.reset();\r
+                               else\r
+                                       --keyer_.depth;\r
                        }\r
                });\r
        }\r
@@ -171,6 +187,7 @@ public:
        {\r
                return ogl_device::begin_invoke([=]() -> safe_ptr<const host_buffer>\r
                {\r
+                       keyer_.depth = 0;\r
                        reading_->map();\r
                        render_targets_[0]->attach(0);\r
                        GL(glClear(GL_COLOR_BUFFER_BIT));\r
@@ -187,6 +204,11 @@ public:
                        std::rotate(render_targets_.begin(), render_targets_.begin() + 1, render_targets_.end());\r
                });\r
        }\r
+\r
+       safe_ptr<device_buffer> create_device_buffer(const core::pixel_format_desc::plane& plane)\r
+       {\r
+               return ogl_device::create_device_buffer(plane.width, plane.height, plane.channels);\r
+       }\r
                \r
        std::vector<safe_ptr<host_buffer>> create_buffers(const core::pixel_format_desc& format)\r
        {\r
index 619fc4cf096d42cfa18d0e7615d6538eae0a6b3a..10334be2d520ee7909dc19dfd5a2b6bac740a93f 100644 (file)
@@ -144,7 +144,7 @@ safe_ptr<basic_frame> basic_frame::fill_and_key(const safe_ptr<basic_frame>& fil
                return fill;\r
 \r
        std::vector<safe_ptr<basic_frame>> frames;\r
-       key->get_image_transform().set_is_key(true);\r
+       key->get_image_transform().set_key_depth(1);\r
        frames.push_back(key);\r
        frames.push_back(fill);\r
        return basic_frame(std::move(frames));\r
index a620a9d4df3c6345d28128cc72bdda5fd3aca9fe..ee1e60f6c6c0e2dab5e55a4fb592e5abd446979f 100644 (file)
@@ -29,7 +29,7 @@ image_transform::image_transform()
        : opacity_(1.0)\r
        , gain_(1.0)\r
        , mode_(video_mode::invalid)\r
-       , is_key_(false)\r
+       , key_depth_(0)\r
 {\r
        std::fill(fill_translation_.begin(), fill_translation_.end(), 0.0);\r
        std::fill(fill_scale_.begin(), fill_scale_.end(), 1.0);\r
@@ -117,7 +117,7 @@ image_transform& image_transform::operator*=(const image_transform &other)
        if(other.mode_ != video_mode::invalid)\r
                mode_ = other.mode_;\r
        gain_ *= other.gain_;\r
-       is_key_ |= other.is_key_;\r
+       key_depth_ = std::max(key_depth_, other.key_depth_);\r
        fill_translation_[0] += other.fill_translation_[0]*fill_scale_[0];\r
        fill_translation_[1] += other.fill_translation_[1]*fill_scale_[1];\r
        fill_scale_[0] *= other.fill_scale_[0];\r
@@ -134,8 +134,8 @@ const image_transform image_transform::operator*(const image_transform &other) c
        return image_transform(*this) *= other;\r
 }\r
 \r
-void image_transform::set_is_key(bool value){is_key_ = value;}\r
-bool image_transform::get_is_key() const{return is_key_;}\r
+void image_transform::set_key_depth(size_t value){key_depth_ = value;}\r
+size_t image_transform::get_key_depth() const {return key_depth_;}\r
 \r
 image_transform tween(double time, const image_transform& source, const image_transform& dest, double duration, const tweener_t& tweener)\r
 {      \r
@@ -148,7 +148,7 @@ image_transform tween(double time, const image_transform& source, const image_tr
 \r
        image_transform result; \r
        result.set_mode(dest.get_mode() != video_mode::invalid ? dest.get_mode() : source.get_mode());\r
-       result.set_is_key(source.get_is_key() | dest.get_is_key());\r
+       result.set_key_depth(std::max(source.get_key_depth(), dest.get_key_depth()));\r
        result.set_gain(do_tween(time, source.get_gain(), dest.get_gain(), duration, tweener));\r
        result.set_opacity(do_tween(time, source.get_opacity(), dest.get_opacity(), duration, tweener));\r
        result.set_fill_translation(do_tween(time, source.get_fill_translation()[0], dest.get_fill_translation()[0], duration, tweener), do_tween(time, source.get_fill_translation()[1], dest.get_fill_translation()[1], duration, tweener));\r
index 7763a7b773b3caecd0f40ac07677a70866eeac6d..e0e6a2a6060175c6916f912fa5b42b91a73c535e 100644 (file)
@@ -58,8 +58,8 @@ public:
        image_transform& operator*=(const image_transform &other);\r
        const image_transform operator*(const image_transform &other) const;\r
 \r
-       void set_is_key(bool value);\r
-       bool get_is_key() const;\r
+       void set_key_depth(size_t depth);\r
+       size_t get_key_depth() const;\r
 private:\r
        double opacity_;\r
        double gain_;\r
@@ -68,7 +68,7 @@ private:
        std::array<double, 2> key_translation_; \r
        std::array<double, 2> key_scale_; \r
        video_mode::type mode_;\r
-       bool is_key_;\r
+       size_t key_depth_;\r
 };\r
 \r
 image_transform tween(double time, const image_transform& source, const image_transform& dest, double duration, const tweener_t& tweener);\r
index d6620ffb015837fba398de7a070cd33b79e51d50..b4eab732e4386181d7bce190f56fb2a25584ac15 100644 (file)
@@ -202,12 +202,12 @@ bool MixerCommand::DoExecute()
        {       \r
                if(_parameters[0] == L"VIDEO")\r
                {\r
-                       if(_parameters[1] == L"IS_KEY")\r
+                       if(_parameters[1] == L"KEY_DEPTH")\r
                        {\r
-                               bool value = lexical_cast_or_default(_parameters.at(2), false);\r
+                               size_t value = lexical_cast_or_default(_parameters.at(2), 0);\r
                                auto transform = [=](image_transform transform) -> image_transform\r
                                {\r
-                                       transform.set_is_key(value);\r
+                                       transform.set_key_depth(value);\r
                                        return transform;                                       \r
                                };\r
 \r
@@ -219,10 +219,9 @@ bool MixerCommand::DoExecute()
                        }\r
                        else if(_parameters[1] == L"OPACITY")\r
                        {\r
-                               int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
-                               std::wstring tween = _parameters.size() > 3 ? _parameters[4] : L"linear";\r
-\r
                                double value = boost::lexical_cast<double>(_parameters.at(2));\r
+                               int duration = _parameters.size() > 3 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 4 ? _parameters[4] : L"linear";\r
                        \r
                                auto transform = [=](image_transform transform) -> image_transform\r
                                {\r
@@ -238,9 +237,9 @@ bool MixerCommand::DoExecute()
                        }\r
                        else if(_parameters[1] == L"GAIN")\r
                        {\r
-                               int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
-                               std::wstring tween = _parameters.size() > 3 ? _parameters[4] : L"linear";\r
                                double value = boost::lexical_cast<double>(_parameters.at(2));\r
+                               int duration = _parameters.size() > 3 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 4 ? _parameters[4] : L"linear";\r
                                \r
                                auto transform = [=](image_transform transform) -> image_transform\r
                                {\r
@@ -256,12 +255,12 @@ bool MixerCommand::DoExecute()
                        }\r
                        else if(_parameters[1] == L"FILL_RECT")\r
                        {\r
-                               int duration = _parameters.size() > 5 ? lexical_cast_or_default(_parameters[6], 0) : 0;\r
-                               std::wstring tween = _parameters.size() > 6 ? _parameters[7] : L"linear";\r
                                double x        = boost::lexical_cast<double>(_parameters.at(2));\r
                                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
+                               int duration = _parameters.size() > 5 ? lexical_cast_or_default(_parameters[6], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 6 ? _parameters[7] : L"linear";\r
 \r
                                auto transform = [=](image_transform transform) -> image_transform\r
                                {\r
@@ -280,12 +279,12 @@ bool MixerCommand::DoExecute()
                        }\r
                        else if(_parameters[1] == L"KEY_RECT")\r
                        {\r
-                               int duration = _parameters.size() > 5 ? lexical_cast_or_default(_parameters[6], 0) : 0;\r
-                               std::wstring tween = _parameters.size() > 6 ? _parameters[7] : L"linear";\r
                                double x        = boost::lexical_cast<double>(_parameters.at(2));\r
                                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
+                               int duration = _parameters.size() > 6 ? lexical_cast_or_default(_parameters[6], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 7 ? _parameters[7] : L"linear";\r
 \r
                                auto transform = [=](image_transform transform) -> image_transform\r
                                {\r
@@ -302,9 +301,10 @@ bool MixerCommand::DoExecute()
                        }\r
                        else if(_parameters[1] == L"GRID")\r
                        {\r
-                               int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
-                               std::wstring tween = _parameters.size() > 3 ? _parameters[4] : L"linear";\r
                                int n = boost::lexical_cast<int>(_parameters.at(2));\r
+                               int duration = _parameters.size() > 3 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 4 ? _parameters[4] : L"linear";\r
+\r
                                double delta = 1.0/static_cast<double>(n);\r
                                for(int x = 0; x < n; ++x)\r
                                {\r
@@ -325,8 +325,8 @@ bool MixerCommand::DoExecute()
                        }\r
                        else if(_parameters[1] == L"RESET")\r
                        {\r
-                               int duration = _parameters.size() > 1 ? lexical_cast_or_default(_parameters[2], 0) : 0;\r
-                               std::wstring tween = _parameters.size() > 2 ? _parameters[3] : L"linear";\r
+                               int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
 \r
                                int layer = GetLayerIndex(std::numeric_limits<int>::min());\r
                                if(layer != std::numeric_limits<int>::min())\r
@@ -339,9 +339,9 @@ bool MixerCommand::DoExecute()
                {\r
                        if(_parameters[1] == L"GAIN")\r
                        {\r
-                               int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
-                               std::wstring tween = _parameters.size() > 3 ? _parameters[4] : L"linear";\r
-                               double value = boost::lexical_cast<double>(_parameters[2]);\r
+                               double value = boost::lexical_cast<double>(_parameters.at(2));\r
+                               int duration = _parameters.size() > 3 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 4 ? _parameters[4] : L"linear";\r
 \r
                                auto transform = [=](audio_transform transform) -> audio_transform\r
                                {\r
@@ -357,15 +357,15 @@ bool MixerCommand::DoExecute()
                        }\r
                        else if(_parameters[1] == L"RESET")\r
                        {\r
-                               int duration = _parameters.size() > 1 ? lexical_cast_or_default(_parameters[2], 0) : 0;\r
-                               std::wstring tween = _parameters.size() > 2 ? _parameters[3] : L"linear";\r
+                               int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
                                GetChannel()->mixer()->reset_audio_transform(duration, tween);\r
                        }\r
                }\r
                else if(_parameters[0] == L"RESET")\r
                {\r
-                       int duration = _parameters.size() > 1 ? lexical_cast_or_default(_parameters[2], 0) : 0;\r
-                       std::wstring tween = _parameters.size() > 2 ? _parameters[3] : L"linear";\r
+                       int duration = _parameters.size() > 1 ? lexical_cast_or_default(_parameters[1], 0) : 0;\r
+                       std::wstring tween = _parameters.size() > 2 ? _parameters[2] : L"linear";\r
                        GetChannel()->mixer()->reset_image_transform(duration, tween);\r
                        GetChannel()->mixer()->reset_audio_transform(duration, tween);\r
                }\r
index d7f3e01b64a1f9f1d5d366c14031715cb8ef968a..1d0709b76e3b95f51fd2e641fd34f0eb7a1e9af6 100644 (file)
@@ -19,7 +19,7 @@
           <embedded-audio>true</embedded-audio>\r
           <latency>low</latency>\r
           <key>external</key>\r
-          <output>key_only</output>\r
+          <output>fill_and_key</output>\r
         </decklink>\r
         <!--<ogl>\r
           <device>1</device>\r