]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2:
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 11 May 2011 20:58:24 +0000 (20:58 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 11 May 2011 20:58:24 +0000 (20:58 +0000)
 separate_producer: It is now possible to have fill and alpha in separate files which are combined during rendering. Simply add a postfix to the alpha file, "_a".
                    Any media file which can be loaded through LOADBG can be used as key, e.g. my_movie.mov, my_movie_a.png or my_movie.mov, my_movia_a.mov.
                    Current limitations of this feature is that the fill media needs to be in either yuv or yuva format (more support will be added in the future).
                    Also no single channel media files are currently supported which results in some uneccessary overhead in the key media file.

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

14 files changed:
core/core.vcxproj
core/core.vcxproj.filters
core/mixer/image/image_kernel.cpp
core/mixer/image/image_kernel.h
core/mixer/image/image_mixer.cpp
core/producer/frame/basic_frame.cpp
core/producer/frame/basic_frame.h
core/producer/frame/image_transform.cpp
core/producer/frame/image_transform.h
core/producer/frame_producer.cpp
core/producer/separated/separated_producer.cpp [new file with mode: 0644]
core/producer/separated/separated_producer.h [new file with mode: 0644]
modules/ffmpeg/producer/ffmpeg_producer.cpp
shell/caspar.config

index 01b1aec250eb0b45062a0b55aaccacbb0e3bf3a0..88eafb503e1715f5d4f8d90c5a124faeda27e172 100644 (file)
     <ClInclude Include="producer\frame_producer.h" />\r
     <ClInclude Include="producer\frame_producer_device.h" />\r
     <ClInclude Include="producer\layer.h" />\r
+    <ClInclude Include="producer\separated\separated_producer.h" />\r
     <ClInclude Include="producer\transition\transition_producer.h" />\r
     <ClInclude Include="video_format.h" />\r
     <CustomBuildStep Include="consumers\bluefish\BluefishException.h" />\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PreprocessToFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</PreprocessToFile>\r
     </ClCompile>\r
+    <ClCompile Include="producer\separated\separated_producer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
     <ClCompile Include="producer\transition\transition_producer.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
index 8475007067709a96093985ef8438fda4272b9de6..a4c9a75c45dbe6cd8d88ba5427eced08a594ceca 100644 (file)
@@ -31,6 +31,9 @@
     <Filter Include="mixer\gpu">\r
       <UniqueIdentifier>{2d2ae7ff-03d7-4e8c-a298-fb41ee42a885}</UniqueIdentifier>\r
     </Filter>\r
+    <Filter Include="producer\separated">\r
+      <UniqueIdentifier>{cf834e89-32d6-47bc-8d5a-10e032f88e15}</UniqueIdentifier>\r
+    </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="producer\transition\transition_producer.h">\r
     <ClInclude Include="mixer\audio\audio_mixer.h">\r
       <Filter>mixer\audio</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="producer\separated\separated_producer.h">\r
+      <Filter>producer\separated</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="producer\transition\transition_producer.cpp">\r
     <ClCompile Include="mixer\audio\audio_mixer.cpp">\r
       <Filter>mixer\audio</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="producer\separated\separated_producer.cpp">\r
+      <Filter>producer\separated</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index 0c5fcd6f7ff5ef41f83de3326d86f27022875b87..c509f1d5989c4647f48b937ff23f06120fe4c93a 100644 (file)
@@ -177,6 +177,7 @@ public:
                        "uniform sampler2D      plane[4];                                                                                       "\r
                        "uniform float          gain;                                                                                           "\r
                        "uniform bool           HD;                                                                                                     "\r
+                       "uniform bool           has_separate_key;                                                                       "\r
                                                                                                                                                                \r
                        // NOTE: YCbCr, ITU-R, http://www.intersil.com/data/an/an9717.pdf               \r
                        // TODO: Support for more yuv formats might be needed.                                  \r
@@ -252,6 +253,8 @@ public:
                        "       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;                            "\r
                        "       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;                            "\r
                        "       float a = 1.0;                                                                                                          "       \r
+                       "       if(has_separate_key)                                                                                            "\r
+                       "               a = texture2D(plane[3], gl_TexCoord[0].st).r+0.2;                                       "\r
                        "       if(HD)                                                                                                                          "\r
                        "               gl_FragColor = ycbcra_to_bgra_hd(y, cb, cr, a) * gl_Color * gain;"\r
                        "       else                                                                                                                            "\r
@@ -278,12 +281,13 @@ public:
 \r
 image_kernel::image_kernel() : impl_(new implementation()){}\r
 \r
-void image_kernel::apply(const core::pixel_format_desc& pix_desc, const core::image_transform& transform)\r
+void image_kernel::apply(const core::pixel_format_desc& pix_desc, const core::image_transform& transform, bool has_separate_key)\r
 {\r
        impl_->shaders()[pix_desc.pix_fmt].use();\r
 \r
        GL(glUniform1f(impl_->shaders()[pix_desc.pix_fmt].get_location("gain"), static_cast<GLfloat>(transform.get_gain())));\r
        GL(glUniform1i(impl_->shaders()[pix_desc.pix_fmt].get_location("HD"), pix_desc.planes.at(0).height > 700 ? 1 : 0));\r
+       GL(glUniform1i(impl_->shaders()[pix_desc.pix_fmt].get_location("has_separate_key"), has_separate_key ? 1 : 0));\r
 \r
        if(transform.get_mode() == core::video_mode::upper)\r
                glPolygonStipple(upper_pattern);\r
index e258249a1fd42f9feea6614d0547afd468f233a5..107da5f01ae02f277ec08b5881391b19f0db37a0 100644 (file)
@@ -30,7 +30,7 @@ class image_kernel
 {\r
 public:\r
        image_kernel();\r
-       void apply(const core::pixel_format_desc& pix_desc, const core::image_transform& mode);\r
+       void apply(const core::pixel_format_desc& pix_desc, const core::image_transform& mode, bool has_seperate_key);\r
 \r
 private:\r
        struct implementation;\r
index aa9741db76445bd0763ebc63d0db97c4a00329f4..cf895df0a0b97576b74d3c901c8dae6d0be7c5b1 100644 (file)
@@ -59,7 +59,7 @@ struct image_mixer::implementation : boost::noncopyable
        image_kernel kernel_;\r
 \r
        safe_ptr<ogl_device> context_;\r
-\r
+       std::shared_ptr<device_buffer> key_;\r
 public:\r
        implementation(const core::video_format_desc& format_desc) \r
                : format_desc_(format_desc)\r
@@ -103,16 +103,13 @@ public:
        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 desc = gpu_frame->get_pixel_format_desc();\r
+               auto buffers = gpu_frame->get_plane_buffers();\r
+               auto is_key_frame = gpu_frame->get_image_transform().get_is_key();\r
 \r
                auto transform = transform_stack_.top();\r
                context_->begin_invoke([=]\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);\r
-\r
                        std::vector<safe_ptr<device_buffer>> device_buffers;\r
                        for(size_t n = 0; n < buffers.size(); ++n)\r
                        {\r
@@ -120,31 +117,51 @@ public:
                                texture->read(*buffers[n]);\r
                                device_buffers.push_back(texture);\r
                        }\r
-\r
-                       for(size_t n = 0; n < buffers.size(); ++n)\r
+                                               \r
+                       if(is_key_frame) // Its a key_frame just bind the texture for use during the next frame.\r
                        {\r
-                               GL(glActiveTexture(GL_TEXTURE0+n));\r
-                               device_buffers[n]->bind();\r
+                               if(!device_buffers.empty())                             \r
+                                       key_ = device_buffers[0];                               \r
                        }\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
+                       else\r
+                       {\r
+                               for(size_t n = 0; n < 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
+                                               \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
                        \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
+                               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
                        \r
-                       auto f_p = transform.get_fill_translation();\r
-                       auto f_s = transform.get_fill_scale();\r
+                               auto f_p = transform.get_fill_translation();\r
+                               auto f_s = transform.get_fill_scale();\r
                        \r
-                       glBegin(GL_QUADS);\r
-                               glTexCoord2d(0.0, 0.0); glVertex2d( f_p[0]        *2.0-1.0,      f_p[1]        *2.0-1.0);\r
-                               glTexCoord2d(1.0, 0.0); glVertex2d((f_p[0]+f_s[0])*2.0-1.0,  f_p[1]        *2.0-1.0);\r
-                               glTexCoord2d(1.0, 1.0); glVertex2d((f_p[0]+f_s[0])*2.0-1.0, (f_p[1]+f_s[1])*2.0-1.0);\r
-                               glTexCoord2d(0.0, 1.0); glVertex2d( f_p[0]        *2.0-1.0, (f_p[1]+f_s[1])*2.0-1.0);\r
-                       glEnd();\r
-                       GL(glDisable(GL_SCISSOR_TEST));\r
+                               glBegin(GL_QUADS);\r
+                                       glTexCoord2d(0.0, 0.0); glVertex2d( f_p[0]        *2.0-1.0,      f_p[1]        *2.0-1.0);\r
+                                       glTexCoord2d(1.0, 0.0); glVertex2d((f_p[0]+f_s[0])*2.0-1.0,  f_p[1]        *2.0-1.0);\r
+                                       glTexCoord2d(1.0, 1.0); glVertex2d((f_p[0]+f_s[0])*2.0-1.0, (f_p[1]+f_s[1])*2.0-1.0);\r
+                                       glTexCoord2d(0.0, 1.0); glVertex2d( f_p[0]        *2.0-1.0, (f_p[1]+f_s[1])*2.0-1.0);\r
+                               glEnd();\r
+                               GL(glDisable(GL_SCISSOR_TEST));\r
+                               \r
+                               key_ = nullptr;\r
+                       }\r
                });\r
        }\r
 \r
index 74e326efeb2ac96fad46e6c6a15fe4da2ae8e238..c8fe03331dbd7e76c73d1e832ed9ba76928e511e 100644 (file)
@@ -127,5 +127,14 @@ safe_ptr<basic_frame> basic_frame::interlace(const safe_ptr<basic_frame>& frame1
        frames.push_back(my_frame2);\r
        return make_safe<basic_frame>(frames);\r
 }\r
+\r
+safe_ptr<basic_frame> basic_frame::fill_and_key(const safe_ptr<basic_frame>& fill, const safe_ptr<basic_frame>& key)\r
+{\r
+       std::vector<safe_ptr<basic_frame>> frames;\r
+       key->get_image_transform().set_is_key(true);\r
+       frames.push_back(key);\r
+       frames.push_back(fill);\r
+       return make_safe<basic_frame>(frames);\r
+}\r
        \r
 }}
\ No newline at end of file
index 9b0bc38a1d2939668e2d1d0081c27c01d6ce4d75..924698d2cfd94b25b6e09cd2ed5d343ba107b6a6 100644 (file)
@@ -62,6 +62,7 @@ public:
        audio_transform& get_audio_transform();\r
                \r
        static safe_ptr<basic_frame> interlace(const safe_ptr<basic_frame>& frame1, const safe_ptr<basic_frame>& frame2, video_mode::type mode);\r
+       static safe_ptr<basic_frame> fill_and_key(const safe_ptr<basic_frame>& fill, const safe_ptr<basic_frame>& key);\r
                \r
        static const safe_ptr<basic_frame>& eof()\r
        {\r
index cba0d9b959db2d2343e2085afafe83ea0c312735..b95a53a5bcfc18f871b0c14a5617f7c8303f0564 100644 (file)
@@ -29,6 +29,7 @@ image_transform::image_transform()
        : opacity_(1.0)\r
        , gain_(1.0)\r
        , mode_(video_mode::invalid)\r
+       , is_key_(false)\r
 {\r
        std::fill(fill_translation_.begin(), fill_translation_.end(), 0.0);\r
        std::fill(fill_scale_.begin(), fill_scale_.end(), 1.0);\r
@@ -116,6 +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
        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
@@ -132,6 +134,9 @@ 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
+\r
 image_transform tween(double time, const image_transform& source, const image_transform& dest, double duration, const tweener_t& tweener)\r
 {      \r
        auto do_tween = [](double time, double source, double dest, double duration, const tweener_t& tweener)\r
@@ -143,6 +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(dest.get_is_key());\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 ed29bbd40d395b1efcaf4af1cb478048b68ccde7..7763a7b773b3caecd0f40ac07677a70866eeac6d 100644 (file)
@@ -57,6 +57,9 @@ public:
 \r
        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
 private:\r
        double opacity_;\r
        double gain_;\r
@@ -65,6 +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
 };\r
 \r
 image_transform tween(double time, const image_transform& source, const image_transform& dest, double duration, const tweener_t& tweener);\r
index e1f910d41e88a86753872bbce45a17a721d372f0..6fe7cd58f5cbb108fe75df063883e7b5d0523ea8 100644 (file)
@@ -22,6 +22,7 @@
 \r
 #include "frame_producer.h"\r
 #include "color/color_producer.h"\r
+#include "separated/separated_producer.h"\r
 \r
 #include <common/memory/safe_ptr.h>\r
 \r
@@ -66,7 +67,7 @@ void register_producer_factory(const producer_factory_t& factory)
        g_factories.push_back(factory);\r
 }\r
 \r
-safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>& my_frame_factory, const std::vector<std::wstring>& params)\r
+safe_ptr<core::frame_producer> do_create_producer(const safe_ptr<frame_factory>& my_frame_factory, const std::vector<std::wstring>& params)\r
 {\r
        if(params.empty())\r
                BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("params") << arg_value_info(""));\r
@@ -94,4 +95,27 @@ safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>& my
        return producer;\r
 }\r
 \r
+\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>& my_frame_factory, const std::vector<std::wstring>& params)\r
+{      \r
+       auto producer = do_create_producer(my_frame_factory, params);\r
+       auto key_producer = frame_producer::empty();\r
+       \r
+       try // to find a key file.\r
+       {\r
+               auto params_copy = params;\r
+               if(params_copy.size() > 0)\r
+               {\r
+                       params_copy[0] += L"_A";\r
+                       key_producer = do_create_producer(my_frame_factory, params_copy);                       \r
+               }\r
+       }\r
+       catch(...){}\r
+\r
+       if(key_producer != frame_producer::empty())\r
+               return create_separated_producer(producer, key_producer);\r
+\r
+       return producer;\r
+}\r
+\r
 }}
\ No newline at end of file
diff --git a/core/producer/separated/separated_producer.cpp b/core/producer/separated/separated_producer.cpp
new file mode 100644 (file)
index 0000000..57aab63
--- /dev/null
@@ -0,0 +1,72 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/ \r
+#include "../../stdafx.h"\r
+\r
+#include "separated_producer.h"\r
+\r
+#include <core/producer/frame/basic_frame.h>\r
+\r
+#include <tbb/parallel_invoke.h>\r
+\r
+namespace caspar { namespace core {    \r
+\r
+struct separated_producer : public frame_producer\r
+{              \r
+       safe_ptr<frame_producer>        fill_producer_;\r
+       safe_ptr<frame_producer>        key_producer;\r
+               \r
+       explicit separated_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key) \r
+               : fill_producer_(fill)\r
+               , key_producer(key){}\r
+       \r
+       // frame_producer\r
+       \r
+       virtual safe_ptr<basic_frame> receive()\r
+       {\r
+               auto fill = basic_frame::empty();\r
+               auto key = basic_frame::empty();\r
+               tbb::parallel_invoke\r
+               (\r
+                       [&]{fill  = receive_and_follow(fill_producer_);},\r
+                       [&]{key   = receive_and_follow(key_producer);}\r
+               );\r
+\r
+               if(fill == basic_frame::eof())\r
+                       return basic_frame::eof();\r
+\r
+               if(key != basic_frame::empty() || key != basic_frame::eof())\r
+                       return basic_frame::fill_and_key(fill, key);\r
+\r
+               return fill;\r
+       }\r
+\r
+       virtual std::wstring print() const\r
+       {\r
+               return L"separed";\r
+       }       \r
+};\r
+\r
+safe_ptr<frame_producer> create_separated_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key)\r
+{\r
+       return make_safe<separated_producer>(fill, key);\r
+}\r
+\r
+}}\r
+\r
diff --git a/core/producer/separated/separated_producer.h b/core/producer/separated/separated_producer.h
new file mode 100644 (file)
index 0000000..3eb41c5
--- /dev/null
@@ -0,0 +1,31 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\r
+*\r
+*    CasparCG is free software: you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation, either version 3 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    CasparCG is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
+#pragma once\r
+\r
+#include "../frame_producer.h"\r
+\r
+#include <string>\r
+#include <memory>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+safe_ptr<frame_producer> create_separated_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key);\r
+\r
+}}
\ No newline at end of file
index 9d8c9ee1c4cb620dd71a1f8d738d55942f9d0bdb..de73eb5c22b13f75fd70e560480f52f289131e25 100644 (file)
@@ -162,6 +162,8 @@ public:
                                        frame->audio_data() = std::move(audio_chunk_channel_.front());\r
                                        audio_chunk_channel_.pop_front();\r
                                }\r
+                               else\r
+                                       frame->get_audio_transform().set_has_audio(false);\r
                                                        \r
                                ouput_channel_.push(make_safe(frame));                          \r
                        }                               \r
index 79dea1f438376caec9b58b500cb42055a0ea9f51..4c1dfaa1cfc77545bf2fa9eb15792d7af895cc4b 100644 (file)
@@ -24,8 +24,8 @@
           <device>0</device>\r
           <stretch>uniform</stretch>\r
           <windowed>true</windowed>\r
-        </ogl>-->\r
-        <!--<audio/>-->\r
+        </ogl>\r
+        <audio/>-->\r
         <!--<bluefish>\r
           <device>1</device>\r
           <embedded-audio>true</embedded-audio>\r