]> git.sesse.net Git - casparcg/commitdiff
* Merged layer_producer and channel_producer from 2.0 to the reroute module (replacin...
authorHelge Norberg <helge.norberg@svt.se>
Thu, 18 Jun 2015 17:34:46 +0000 (19:34 +0200)
committerHelge Norberg <helge.norberg@svt.se>
Thu, 18 Jun 2015 17:34:46 +0000 (19:34 +0200)
* In order to support route:// without the same intrusive changes in AMCPCommandsImpl.cpp from 2.0, refactored so that every producer factory gets a list of channels.
* Refactored so that frame_factory and video_format_desc is now part of a type called frame_producer_dependencies. The list of channels needed by reroute producer was also added to this class. Future dependencies will not need a change in the signature of every producer factory.
* Fixed possible race condition in stage.cpp where std::map could be modified from multiple threads

51 files changed:
core/CMakeLists.txt
core/consumer/write_frame_consumer.h [new file with mode: 0644]
core/fwd.h
core/producer/cg_proxy.cpp
core/producer/cg_proxy.h
core/producer/frame_producer.cpp
core/producer/frame_producer.h
core/producer/scene/scene_producer.cpp
core/producer/scene/scene_producer.h
core/producer/scene/xml_scene_producer.cpp
core/producer/scene/xml_scene_producer.h
core/producer/stage.cpp
core/producer/stage.h
core/producer/text/text_producer.cpp
core/producer/text/text_producer.h
core/thumbnail_generator.cpp
core/video_channel.cpp
modules/decklink/producer/decklink_producer.cpp
modules/decklink/producer/decklink_producer.h
modules/ffmpeg/producer/ffmpeg_producer.cpp
modules/ffmpeg/producer/ffmpeg_producer.h
modules/flash/flash.cpp
modules/flash/producer/flash_producer.cpp
modules/flash/producer/flash_producer.h
modules/html/html.cpp
modules/html/producer/html_producer.cpp
modules/html/producer/html_producer.h
modules/image/producer/image_producer.cpp
modules/image/producer/image_producer.h
modules/image/producer/image_scroll_producer.cpp
modules/image/producer/image_scroll_producer.h
modules/psd/psd_scene_producer.cpp
modules/reroute/CMakeLists.txt
modules/reroute/producer/channel_producer.cpp [new file with mode: 0644]
modules/reroute/producer/channel_producer.h [new file with mode: 0644]
modules/reroute/producer/layer_producer.cpp [new file with mode: 0644]
modules/reroute/producer/layer_producer.h [new file with mode: 0644]
modules/reroute/producer/reroute_producer.cpp
modules/reroute/producer/reroute_producer.h
modules/reroute/reroute.cpp [new file with mode: 0644]
modules/reroute/reroute.h [new file with mode: 0644]
protocol/amcp/AMCPCommand.h
protocol/amcp/AMCPCommandsImpl.cpp
protocol/amcp/AMCPCommandsImpl.h
protocol/amcp/AMCPProtocolStrategy.cpp
protocol/cii/CIICommandsImpl.cpp
protocol/cii/CIIProtocolStrategy.cpp
protocol/cii/CIIProtocolStrategy.h
protocol/clk/CLKProtocolStrategy.cpp
protocol/clk/clk_commands.cpp
protocol/clk/clk_commands.h

index 057825719d9bc54e3f1d6f5be49a91af8ad22e04..8f8a12a0c98957c4affce269fc5b16b617c6f957 100644 (file)
@@ -57,6 +57,7 @@ set(HEADERS
                consumer/frame_consumer.h
                consumer/output.h
                consumer/port.h
+               consumer/write_frame_consumer.h
 
                diagnostics/call_context.h
                diagnostics/osd_graph.h
diff --git a/core/consumer/write_frame_consumer.h b/core/consumer/write_frame_consumer.h
new file mode 100644 (file)
index 0000000..cc53c7c
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Cambell Prince, cambell.prince@gmail.com
+*/
+
+#pragma once
+
+#include "../fwd.h"
+
+#include <common/memory.h>
+
+#include <boost/noncopyable.hpp>
+#include <boost/property_tree/ptree_fwd.hpp>
+
+#include <functional>
+#include <string>
+#include <vector>
+
+namespace caspar { namespace core {
+       
+struct write_frame_consumer : boost::noncopyable
+{
+       virtual ~write_frame_consumer() {}
+       
+       virtual void send(const draw_frame& frame) = 0;
+       virtual std::wstring print() const = 0;
+       //virtual boost::property_tree::wptree info() const = 0;
+};
+
+}}
\ No newline at end of file
index d07c43a7cf932e726740c7cab671e5b11344a2be..cea52bb83dbebcb50666680c80dbf148276e9628 100644 (file)
@@ -44,4 +44,5 @@ FORWARD2(caspar, core, class thumbnail_generator);
 FORWARD2(caspar, core, class system_info_provider_repository);
 FORWARD2(caspar, core, class cg_producer_registry);
 FORWARD2(caspar, core, struct frame_transform);
-
+FORWARD2(caspar, core, struct write_frame_consumer);
+FORWARD2(caspar, core, struct frame_producer_dependencies);
index a2b045885421c305a4682c0865d598f80616e758..8c321dc98632460121b60616e0391c43b7ac3208 100644 (file)
@@ -107,7 +107,7 @@ public:
        }
 
        spl::shared_ptr<frame_producer> create_producer(
-                       const spl::shared_ptr<video_channel>& video_channel,
+                       const frame_producer_dependencies& dependencies,
                        const std::wstring& filename) const
        {
                auto found = find_record(filename);
@@ -115,10 +115,7 @@ public:
                if (!found)
                        return frame_producer::empty();
 
-               return found->producer_factory(
-                               video_channel->frame_factory(),
-                               video_channel->video_format_desc(),
-                               filename);
+               return found->producer_factory(dependencies, filename);
        }
 
        spl::shared_ptr<cg_proxy> get_proxy(const spl::shared_ptr<frame_producer>& producer) const
@@ -147,6 +144,7 @@ public:
 
        spl::shared_ptr<cg_proxy> get_or_create_proxy(
                        const spl::shared_ptr<video_channel>& video_channel,
+                       const frame_producer_dependencies& dependencies,
                        int render_layer,
                        const std::wstring& filename) const
        {
@@ -167,10 +165,7 @@ public:
                        diagnostics::call_context::for_thread().video_channel = video_channel->index();
                        diagnostics::call_context::for_thread().layer = render_layer;
 
-                       producer = found->producer_factory(
-                                       video_channel->frame_factory(),
-                                       video_channel->video_format_desc(),
-                                       filename);
+                       producer = found->producer_factory(dependencies, filename);
                        video_channel->stage().load(render_layer, producer);
                        video_channel->stage().play(render_layer);
                }
@@ -245,10 +240,10 @@ void cg_producer_registry::register_cg_producer(
 }
 
 spl::shared_ptr<frame_producer> cg_producer_registry::create_producer(
-               const spl::shared_ptr<video_channel>& video_channel,
+               const frame_producer_dependencies& dependencies,
                const std::wstring& filename) const
 {
-       return impl_->create_producer(video_channel, filename);
+       return impl_->create_producer(dependencies, filename);
 }
 
 spl::shared_ptr<cg_proxy> cg_producer_registry::get_proxy(
@@ -266,10 +261,11 @@ spl::shared_ptr<cg_proxy> cg_producer_registry::get_proxy(
 
 spl::shared_ptr<cg_proxy> cg_producer_registry::get_or_create_proxy(
                const spl::shared_ptr<video_channel>& video_channel,
+               const frame_producer_dependencies& dependencies,
                int render_layer,
                const std::wstring& filename) const
 {
-       return impl_->get_or_create_proxy(video_channel, render_layer, filename);
+       return impl_->get_or_create_proxy(video_channel, dependencies, render_layer, filename);
 }
 
 std::string cg_producer_registry::read_meta_info(const std::wstring& filename) const
index 76ea8fad61d9c875111aebf52078de73e9e77255..77713a663711a731871f005af093388a51f0dc90 100644 (file)
@@ -57,8 +57,7 @@ typedef std::function<spl::shared_ptr<cg_proxy>(
                const spl::shared_ptr<frame_producer>& producer
        )> cg_proxy_factory;
 typedef std::function<spl::shared_ptr<frame_producer>(
-               const spl::shared_ptr<frame_factory>& factory,
-               const video_format_desc& format_desc,
+               const frame_producer_dependencies& dependencies,
                const std::wstring& filename
        )> cg_producer_factory;
 typedef std::function<std::string(const std::wstring& filename)> meta_info_extractor;
@@ -77,7 +76,7 @@ public:
                        bool reusable_producer_instance);
 
        spl::shared_ptr<frame_producer> create_producer(
-                       const spl::shared_ptr<video_channel>& video_channel,
+                       const frame_producer_dependencies& dependencies,
                        const std::wstring& filename) const;
        spl::shared_ptr<cg_proxy> get_proxy(
                        const spl::shared_ptr<frame_producer>& producer) const;
@@ -86,6 +85,7 @@ public:
                        int render_layer) const;
        spl::shared_ptr<cg_proxy> get_or_create_proxy(
                        const spl::shared_ptr<video_channel>& video_channel,
+                       const frame_producer_dependencies& dependencies,
                        int render_layer,
                        const std::wstring& filename) const;
        std::string read_meta_info(const std::wstring& filename) const;
index f1f6907d244fc92b010e0271937f340a2abff064..5cc009ad8ec053c8d9016e2ca1c52bb9ed7fde4e 100644 (file)
@@ -53,6 +53,16 @@ void register_thumbnail_producer_factory(const producer_factory_t& factory)
        g_thumbnail_factories.push_back(factory);
 }
 
+frame_producer_dependencies::frame_producer_dependencies(
+               const spl::shared_ptr<core::frame_factory>& frame_factory,
+               const std::vector<spl::shared_ptr<video_channel>>& channels,
+               const video_format_desc& format_desc)
+       : frame_factory(frame_factory)
+       , channels(channels)
+       , format_desc(format_desc)
+{
+}
+
 constraints::constraints(double width, double height)
        : width(width), height(height)
 {
@@ -262,7 +272,7 @@ spl::shared_ptr<core::frame_producer> create_destroy_proxy(spl::shared_ptr<core:
        return spl::make_shared<destroy_producer_proxy>(std::move(producer));
 }
 
-spl::shared_ptr<core::frame_producer> do_create_producer(const spl::shared_ptr<frame_factory>& my_frame_factory, const video_format_desc& format_desc, const std::vector<std::wstring>& params, const std::vector<producer_factory_t>& factories, bool throw_on_fail = false)
+spl::shared_ptr<core::frame_producer> do_create_producer(const frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params, const std::vector<producer_factory_t>& factories, bool throw_on_fail = false)
 {
        if(params.empty())
                CASPAR_THROW_EXCEPTION(invalid_argument() << arg_name_info("params") << arg_value_info(""));
@@ -272,7 +282,7 @@ spl::shared_ptr<core::frame_producer> do_create_producer(const spl::shared_ptr<f
                {
                        try
                        {
-                               producer = factory(my_frame_factory, format_desc, params);
+                               producer = factory(dependencies, params);
                        }
                        catch(...)
                        {
@@ -285,10 +295,10 @@ spl::shared_ptr<core::frame_producer> do_create_producer(const spl::shared_ptr<f
                });
 
        if(producer == frame_producer::empty())
-               producer = create_color_producer(my_frame_factory, params);
+               producer = create_color_producer(dependencies.frame_factory, params);
 
        if (producer == frame_producer::empty())
-               producer = create_freehand_producer(my_frame_factory, params);
+               producer = create_freehand_producer(dependencies.frame_factory, params);
 
        if(producer == frame_producer::empty())
                return producer;
@@ -296,12 +306,12 @@ spl::shared_ptr<core::frame_producer> do_create_producer(const spl::shared_ptr<f
        return producer;
 }
 
-spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const spl::shared_ptr<frame_factory>& my_frame_factory, const video_format_desc& format_desc, const std::wstring& media_file)
+spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const frame_producer_dependencies& dependencies, const std::wstring& media_file)
 {
   std::vector<std::wstring> params;
   params.push_back(media_file);
 
-  auto producer = do_create_producer(my_frame_factory, format_desc, params, g_thumbnail_factories, true);
+  auto producer = do_create_producer(dependencies, params, g_thumbnail_factories, true);
   auto key_producer = frame_producer::empty();
   
   try // to find a key file.
@@ -310,11 +320,11 @@ spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const spl::share
        if (params_copy.size() > 0)
        {
          params_copy[0] += L"_A";
-         key_producer = do_create_producer(my_frame_factory, format_desc, params_copy, g_thumbnail_factories, true);
+         key_producer = do_create_producer(dependencies, params_copy, g_thumbnail_factories, true);
          if (key_producer == frame_producer::empty())
          {
                params_copy[0] += L"LPHA";
-               key_producer = do_create_producer(my_frame_factory, format_desc, params_copy, g_thumbnail_factories, true);
+               key_producer = do_create_producer(dependencies, params_copy, g_thumbnail_factories, true);
          }
        }
   }
@@ -326,9 +336,9 @@ spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const spl::share
   return producer;
 }
 
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<frame_factory>& my_frame_factory, const video_format_desc& format_desc, const std::vector<std::wstring>& params)
+spl::shared_ptr<core::frame_producer> create_producer(const frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
 {      
-       auto producer = do_create_producer(my_frame_factory, format_desc, params, g_producer_factories);
+       auto producer = do_create_producer(dependencies, params, g_producer_factories);
        auto key_producer = frame_producer::empty();
        
        try // to find a key file.
@@ -337,11 +347,11 @@ spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<fram
                if(params_copy.size() > 0)
                {
                        params_copy[0] += L"_A";
-                       key_producer = do_create_producer(my_frame_factory, format_desc, params_copy, g_producer_factories);
+                       key_producer = do_create_producer(dependencies, params_copy, g_producer_factories);
                        if(key_producer == frame_producer::empty())
                        {
                                params_copy[0] += L"LPHA";
-                               key_producer = do_create_producer(my_frame_factory, format_desc, params_copy, g_producer_factories);
+                               key_producer = do_create_producer(dependencies, params_copy, g_producer_factories);
                        }
                }
        }
@@ -362,13 +372,13 @@ spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<fram
 }
 
 
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<frame_factory>& factory, const video_format_desc& format_desc, const std::wstring& params)
+spl::shared_ptr<core::frame_producer> create_producer(const frame_producer_dependencies& dependencies, const std::wstring& params)
 {
        std::wstringstream iss(params);
        std::vector<std::wstring> tokens;
        typedef std::istream_iterator<std::wstring, wchar_t, std::char_traits<wchar_t> > iterator;
        std::copy(iterator(iss),  iterator(), std::back_inserter(tokens));
-       return create_producer(factory, format_desc, tokens);
+       return create_producer(dependencies, tokens);
 }
 
 }}
index f0b0dcb71af17f054d3960105bb065a9290f87b2..5a857d9b7f8319877dadbb9a0eb67a3ddc3572c5 100644 (file)
@@ -131,14 +131,26 @@ private:
        std::shared_ptr<impl> impl_;
 };
 
-typedef std::function<spl::shared_ptr<core::frame_producer>(const spl::shared_ptr<class frame_factory>&, const video_format_desc& format_desc, const std::vector<std::wstring>&)> producer_factory_t;
+struct frame_producer_dependencies
+{
+       spl::shared_ptr<core::frame_factory>            frame_factory;
+       std::vector<spl::shared_ptr<video_channel>>     channels;
+       video_format_desc                                                       format_desc;
+
+       frame_producer_dependencies(
+                       const spl::shared_ptr<core::frame_factory>& frame_factory,
+                       const std::vector<spl::shared_ptr<video_channel>>& channels,
+                       const video_format_desc& format_desc);
+};
+
+typedef std::function<spl::shared_ptr<core::frame_producer>(const frame_producer_dependencies&, const std::vector<std::wstring>&)> producer_factory_t;
 void register_producer_factory(const producer_factory_t& factory); // Not thread-safe.
 void register_thumbnail_producer_factory(const producer_factory_t& factory); // Not thread-safe.
 
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<frame_factory>&, const video_format_desc& format_desc, const std::vector<std::wstring>& params);
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<frame_factory>&, const video_format_desc& format_desc, const std::wstring& params);
+spl::shared_ptr<core::frame_producer> create_producer(const frame_producer_dependencies&, const std::vector<std::wstring>& params);
+spl::shared_ptr<core::frame_producer> create_producer(const frame_producer_dependencies&, const std::wstring& params);
 
 spl::shared_ptr<core::frame_producer> create_destroy_proxy(spl::shared_ptr<core::frame_producer> producer);
-spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const spl::shared_ptr<frame_factory>&, const video_format_desc& format_desc, const std::wstring& media_file);
+spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const frame_producer_dependencies&, const std::wstring& media_file);
 
 }}
index ea447741f8de5b391306e4bda5a6b8f3b6eedfe1..2f4956063324e630f6b7a958ecd2efed89316e79 100644 (file)
@@ -606,114 +606,4 @@ const std::vector<std::wstring>& scene_producer::get_variables() const
        return impl_->get_variables();
 }
 
-spl::shared_ptr<core::frame_producer> create_dummy_scene_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const video_format_desc& format_desc, const std::vector<std::wstring>& params)
-{
-       if (params.size() < 1 || !boost::iequals(params.at(0), L"[SCENE]"))
-               return core::frame_producer::empty();
-
-       auto scene = spl::make_shared<scene_producer>(format_desc.width, format_desc.height, format_desc);
-
-       text::text_info text_info;
-       text_info.font = L"ArialMT";
-       text_info.size = 62;
-       text_info.color.r = 1;
-       text_info.color.g = 1;
-       text_info.color.b = 1;
-       text_info.color.a = 0.5;
-       auto text_area = text_producer::create(frame_factory, 0, 0, L"a", text_info, 1280, 720, false);
-
-       auto text_width = text_area->pixel_constraints().width;
-       binding<double> padding(1.0);
-       binding<double> panel_width = padding + text_width + padding;
-       binding<double> panel_height = padding + text_area->pixel_constraints().height + padding;
-
-       auto subscription = panel_width.on_change([&]
-       {
-               CASPAR_LOG(info) << "Panel width: " << panel_width.get();
-       });
-
-       padding.set(2);
-
-       auto create_param = [](std::wstring elem) -> std::vector<std::wstring>
-       {
-               std::vector<std::wstring> result;
-               result.push_back(elem);
-               return result;
-       };
-
-       auto& car_layer = scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"car")), L"car");
-       car_layer.adjustments.opacity.set(0.5);
-       //car_layer.hidden = scene->frame() % 50 > 25 || !(scene->frame() < 1000);
-       std::vector<std::wstring> sub_params;
-       sub_params.push_back(L"[FREEHAND]");
-       sub_params.push_back(L"640");
-       sub_params.push_back(L"360");
-       scene->create_layer(create_producer(frame_factory, format_desc, sub_params), 10, 10, L"freehand");
-       sub_params.clear();
-
-       auto& color_layer = scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"RED")), 110, 10, L"color");
-       color_layer.producer.get()->pixel_constraints().width.set(1000);
-       color_layer.producer.get()->pixel_constraints().height.set(550);
-
-       //scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"SP")), 50, 50);
-
-       auto& upper_left = scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"scene/upper_left")), L"upper_left");
-       auto& upper_right = scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"scene/upper_right")), L"upper_right");
-       auto& lower_left = scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"scene/lower_left")), L"lower_left");
-       auto& lower_right = scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"scene/lower_right")), L"lower_right");
-       auto& text_layer = scene->create_layer(text_area, L"text_area");
-       upper_left.adjustments.opacity.bind(text_layer.adjustments.opacity);
-       upper_right.adjustments.opacity.bind(text_layer.adjustments.opacity);
-       lower_left.adjustments.opacity.bind(text_layer.adjustments.opacity);
-       lower_right.adjustments.opacity.bind(text_layer.adjustments.opacity);
-
-       /*
-       binding<double> panel_x = (scene->frame()
-                       .as<double>()
-                       .transformed([](double v) { return std::sin(v / 20.0); })
-                       * 20.0
-                       + 40.0)
-                       .transformed([](double v) { return std::floor(v); }); // snap to pixels instead of subpixels
-                       */
-       tweener tween(L"easeoutbounce");
-       binding<double> panel_x(0.0);
-
-       scene->add_keyframe(panel_x, -panel_width, 0);
-       scene->add_keyframe(panel_x, 300.0, 50, L"easeinoutsine");
-       scene->add_keyframe(panel_x, 300.0, 50 * 4);
-       scene->add_keyframe(panel_x, 1000.0, 50 * 5, L"easeinoutsine");
-       //panel_x = delay(panel_x, add_tween(panel_x, scene->frame(), 200.0, int64_t(50), L"linear"), scene->frame(), int64_t(100));
-       /*binding<double> panel_x = when(scene->frame() < 50)
-               .then(scene->frame().as<double>().transformed([tween](double t) { return tween(t, 0.0, 200, 50); }))
-               .otherwise(200.0);*/
-       //binding<double> panel_y = when(car_layer.hidden).then(500.0).otherwise(-panel_x + 300);
-       binding<double> panel_y(500.0);
-       scene->add_keyframe(panel_y, panel_y.get(), 50 * 4);
-       scene->add_keyframe(panel_y, 720.0, 50 * 5, L"easeinexpo");
-
-       scene->add_keyframe(text_layer.adjustments.opacity, 1.0, 100);
-       scene->add_keyframe(text_layer.adjustments.opacity, 0.0, 125, L"linear");
-       scene->add_keyframe(text_layer.adjustments.opacity, 1.0, 150, L"linear");
-
-       upper_left.position.x = panel_x;
-       upper_left.position.y = panel_y;
-       upper_right.position.x = upper_left.position.x + upper_left.producer.get()->pixel_constraints().width + panel_width;
-       upper_right.position.y = upper_left.position.y;
-       lower_left.position.x = upper_left.position.x;
-       lower_left.position.y = upper_left.position.y + upper_left.producer.get()->pixel_constraints().height + panel_height;
-       lower_right.position.x = upper_right.position.x;
-       lower_right.position.y = lower_left.position.y;
-       text_layer.position.x = upper_left.position.x + upper_left.producer.get()->pixel_constraints().width + padding;
-       text_layer.position.y = upper_left.position.y + upper_left.producer.get()->pixel_constraints().height + padding + text_area->current_bearing_y().as<double>();
-
-       text_area->text().bind(scene->create_variable<std::wstring>(L"text", true));
-
-       auto params2 = params;
-       params2.erase(params2.begin());
-
-       scene->call(params2);
-
-       return scene;
-}
-
 }}}
index 9ed41463eae1cd736104e0da337c6d9e31df4a08..21710d213670627b449d5318eca5c1a7e3bd2f83 100644 (file)
@@ -232,6 +232,4 @@ private:
        std::unique_ptr<impl> impl_;
 };
 
-spl::shared_ptr<frame_producer> create_dummy_scene_producer(const spl::shared_ptr<frame_factory>& frame_factory, const video_format_desc& format_desc, const std::vector<std::wstring>& params);
-
 }}}
index aae04601423a07c603fd87e0dd937092318ac08b..23c83729f348646dcf7497190d0f5cb76da8d3d7 100644 (file)
@@ -73,18 +73,16 @@ void init(module_dependencies dependencies)
                                return spl::make_shared<core::scene::scene_cg_proxy>(producer);
                        },
                        [](
-                       const spl::shared_ptr<core::frame_factory>& factory,
-                       const core::video_format_desc& format_desc,
-                       const std::wstring& filename)
+                                       const core::frame_producer_dependencies& dependencies,
+                                       const std::wstring& filename)
                        {
-                               return create_xml_scene_producer(factory, format_desc, { filename });
+                               return create_xml_scene_producer(dependencies, { filename });
                        },
                        false);
 }
 
 spl::shared_ptr<core::frame_producer> create_xml_scene_producer(
-               const spl::shared_ptr<core::frame_factory>& frame_factory,
-               const core::video_format_desc& format_desc,
+               const core::frame_producer_dependencies& dependencies,
                const std::vector<std::wstring>& params)
 {
        if (params.empty())
@@ -106,7 +104,7 @@ spl::shared_ptr<core::frame_producer> create_xml_scene_producer(
        int width = root.get<int>(L"scene.<xmlattr>.width");
        int height = root.get<int>(L"scene.<xmlattr>.height");
 
-       auto scene = spl::make_shared<scene_producer>(width, height, format_desc);
+       auto scene = spl::make_shared<scene_producer>(width, height, dependencies.format_desc);
 
        for (auto elem : root.get_child(L"scene.variables"))
        {
@@ -129,7 +127,7 @@ spl::shared_ptr<core::frame_producer> create_xml_scene_producer(
        for (auto& elem : root.get_child(L"scene.layers"))
        {
                auto id = elem.second.get<std::wstring>(L"<xmlattr>.id");
-               auto producer = create_producer(frame_factory, format_desc, elem.second.get<std::wstring>(L"producer"));
+               auto producer = create_producer(dependencies, elem.second.get<std::wstring>(L"producer"));
                auto& layer = scene->create_layer(producer, 0, 0, id);
                auto variable_prefix = L"layer." + id + L".";
 
index effb39e8ef33004e306db03cb6cff6a3073c7d3c..abae354545f5f49d6b0df7c47999eca008abddd8 100644 (file)
@@ -31,6 +31,6 @@
 namespace caspar { namespace core { namespace scene {
 
 void init(module_dependencies dependencies);
-spl::shared_ptr<core::frame_producer> create_xml_scene_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
+spl::shared_ptr<core::frame_producer> create_xml_scene_producer(const frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params);
 
 }}}
index cda09dac54d3980115297b036bfb3bb382cc7cf1..992554ef4f0e153f986c54e7c65f00f1c0419def 100644 (file)
@@ -28,6 +28,7 @@
 #include "../frame/draw_frame.h"
 #include "../frame/frame_factory.h"
 #include "../interaction/interaction_aggregator.h"
+#include "../consumer/write_frame_consumer.h"
 
 #include <common/executor.h>
 #include <common/future.h>
@@ -49,13 +50,15 @@ namespace caspar { namespace core {
        
 struct stage::impl : public std::enable_shared_from_this<impl>
 {                              
-       spl::shared_ptr<diagnostics::graph>                                                     graph_;
-       spl::shared_ptr<monitor::subject>                                                       monitor_subject_;
-       //reactive::basic_subject<std::map<int, draw_frame>>            frames_subject_;
-       std::map<int, layer>                                                                            layers_;        
-       std::map<int, tweened_transform>                                                        tweens_;
-       interaction_aggregator                                                                          aggregator_;
-       executor                                                                                                        executor_;
+       spl::shared_ptr<diagnostics::graph>                                                                             graph_;
+       spl::shared_ptr<monitor::subject>                                                                               monitor_subject_;
+       //reactive::basic_subject<std::map<int, draw_frame>>                                    frames_subject_;
+       std::map<int, layer>                                                                                                    layers_;        
+       std::map<int, tweened_transform>                                                                                tweens_;
+       interaction_aggregator                                                                                                  aggregator_;
+       // map of layer -> map of tokens (src ref) -> layer_consumer
+       std::map<int, std::map<void*, spl::shared_ptr<write_frame_consumer>>>   layer_consumers_;
+       executor                                                                                                                                executor_;
 public:
        impl(spl::shared_ptr<diagnostics::graph> graph) 
                : graph_(std::move(graph))
@@ -81,7 +84,11 @@ public:
 
                                for (auto& layer : layers_)     
                                {
-                                       frames[layer.first] = draw_frame::empty();      
+                                       // Prevent race conditions in parallel for each later
+                                       frames[layer.first] = draw_frame::empty();
+                                       tweens_[layer.first];
+                                       layer_consumers_[layer.first];
+
                                        indices.push_back(layer.first);
                                }
 
@@ -114,9 +121,21 @@ public:
        {
                auto& layer             = layers_[index];
                auto& tween             = tweens_[index];
-                               
+               auto& consumers = layer_consumers_[index];
+
                auto frame  = layer.receive(format_desc);                                       
+               
+               if (!consumers.empty())
+               {
+                       auto consumer_it = consumers | boost::adaptors::map_values;
+                       tbb::parallel_for_each(consumer_it.begin(), consumer_it.end(), [&](decltype(*consumer_it.begin()) layer_consumer)
+                       {
+                               layer_consumer->send(frame);
+                       });
+               }
+
                auto frame1 = frame;
+               
                frame1.transform() *= tween.fetch_and_tick(1);
 
                if(format_desc.field_mode != core::field_mode::progressive)
@@ -306,7 +325,28 @@ public:
                        }, task_priority::high_priority);
                }
        }
-               
+
+       void add_layer_consumer(void* token, int layer, const spl::shared_ptr<write_frame_consumer>& layer_consumer)
+       {
+               executor_.begin_invoke([=]
+               {
+                       layer_consumers_[layer].insert(std::make_pair(token, layer_consumer));
+               }, task_priority::high_priority);
+       }
+
+       void remove_layer_consumer(void* token, int layer)
+       {
+               executor_.begin_invoke([=]
+               {
+                       auto& layer_map = layer_consumers_[layer];
+                       layer_map.erase(token);
+                       if (layer_map.empty())
+                       {
+                               layer_consumers_.erase(layer);
+                       }
+               }, task_priority::high_priority);
+       }
+
        std::future<std::shared_ptr<frame_producer>> foreground(int index)
        {
                return executor_.begin_invoke([=]() -> std::shared_ptr<frame_producer>
@@ -396,7 +436,8 @@ std::future<void> stage::clear(){ return impl_->clear(); }
 std::future<void> stage::swap_layers(stage& other){ return impl_->swap_layers(other); }
 std::future<void> stage::swap_layer(int index, int other_index){ return impl_->swap_layer(index, other_index); }
 std::future<void> stage::swap_layer(int index, int other_index, stage& other){ return impl_->swap_layer(index, other_index, other); }
-std::future<std::shared_ptr<frame_producer>> stage::foreground(int index) { return impl_->foreground(index); }
+void stage::add_layer_consumer(void* token, int layer, const spl::shared_ptr<write_frame_consumer>& layer_consumer){ impl_->add_layer_consumer(token, layer, layer_consumer); }
+void stage::remove_layer_consumer(void* token, int layer){ impl_->remove_layer_consumer(token, layer); }std::future<std::shared_ptr<frame_producer>> stage::foreground(int index) { return impl_->foreground(index); }
 std::future<std::shared_ptr<frame_producer>> stage::background(int index) { return impl_->background(index); }
 std::future<boost::property_tree::wptree> stage::info() const{ return impl_->info(); }
 std::future<boost::property_tree::wptree> stage::info(int index) const{ return impl_->info(index); }
index 1a606c1316e99ed2442bed526694873471f064a1..0a2ded3990383a416a019277916ecb2a8461b51b 100644 (file)
@@ -21,8 +21,7 @@
 
 #pragma once
 
-#include "frame_producer.h"
-
+#include "../fwd.h"
 #include "../monitor/monitor.h"
 #include "../interaction/interaction_sink.h"
 
@@ -49,7 +48,7 @@ class stage final : public interaction_sink
 {
        stage(const stage&);
        stage& operator=(const stage&);
-public:        
+public:
 
        // Static Members
        
@@ -80,6 +79,9 @@ public:
        std::future<void>                               swap_layer(int index, int other_index);
        std::future<void>                               swap_layer(int index, int other_index, stage& other);
 
+       void                                                    add_layer_consumer(void* token, int layer, const spl::shared_ptr<write_frame_consumer>& layer_consumer);
+       void                                                    remove_layer_consumer(void* token, int layer);
+
        monitor::subject& monitor_output();     
 
        // frame_observable
index e43213814bacdae1528082862e368ccc74ebcd73..c8b79b35286b332a608f1bcb93b394b4be165773 100644 (file)
@@ -315,7 +315,7 @@ spl::shared_ptr<text_producer> text_producer::create(const spl::shared_ptr<frame
        return spl::make_shared<text_producer>(frame_factory, x, y, str, text_info, parent_width, parent_height, standalone);
 }
 
-spl::shared_ptr<frame_producer> create_text_producer(const spl::shared_ptr<frame_factory>& frame_factory, const video_format_desc& format_desc, const std::vector<std::wstring>& params)
+spl::shared_ptr<frame_producer> create_text_producer(const frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
 {
        if(params.size() < 2 || !boost::iequals(params.at(0), L"[text]"))
                return core::frame_producer::empty();
@@ -338,7 +338,13 @@ spl::shared_ptr<frame_producer> create_text_producer(const spl::shared_ptr<frame
 
        bool standalone = get_param(L"STANDALONE", params, false);
 
-       return text_producer::create(frame_factory, x, y, params.at(1), text_info, format_desc.width, format_desc.height, standalone);
+       return text_producer::create(
+                       dependencies.frame_factory,
+                       x, y,
+                       params.at(1),
+                       text_info,
+                       dependencies.format_desc.width, dependencies.format_desc.height,
+                       standalone);
 }
 
 }}
index a1cc7c0d405113400daca90f42902038860fbc1d..197c94895091ffa338b6d8c3e746944aabd7238d 100644 (file)
@@ -68,7 +68,7 @@ private:
        spl::unique_ptr<impl> impl_;
 };
 
-spl::shared_ptr<frame_producer> create_text_producer(const spl::shared_ptr<frame_factory>& frame_factory, const video_format_desc& format_desc, const std::vector<std::wstring>& params);
+spl::shared_ptr<frame_producer> create_text_producer(const frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params);
 
 
 }}
index cc26be2b6838d806802047c90e9aca9fdbde44b3..8a27cba25a1ccd192fd47d3adebe3abef103fda4 100644 (file)
@@ -267,7 +267,9 @@ public:
 
                        try
                        {
-                               producer = create_thumbnail_producer(image_mixer_, format_desc_, media_file);
+                               producer = create_thumbnail_producer(
+                                               frame_producer_dependencies(image_mixer_, { }, format_desc_),
+                                               media_file);
                        }
                        catch (const boost::thread_interrupted&)
                        {
index 17b1e4df1435348a9390a57cb9b08b953cad7d0e..fcd79535bafad631dc032a8cd5c14266d6762ba3 100644 (file)
@@ -44,6 +44,7 @@
 #include <tbb/spin_mutex.h>
 
 #include <boost/property_tree/ptree.hpp>
+#include <boost/lexical_cast.hpp>
 
 #include <string>
 
index 7edafadffefd4733b0197e5314a810790e1664fe..0134b7448b7cc1115b2cd84e775c5b23fa33cdbb 100644 (file)
@@ -41,6 +41,7 @@
 #include <core/frame/draw_frame.h>
 #include <core/frame/frame_transform.h>
 #include <core/frame/frame_factory.h>
+#include <core/producer/frame_producer.h>
 #include <core/monitor/monitor.h>
 #include <core/mixer/audio/audio_mixer.h>
 
@@ -362,7 +363,7 @@ public:
        }
 };
 
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& out_format_desc, const std::vector<std::wstring>& params)
+spl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
 {
        if(params.empty() || !boost::iequals(params.at(0), "decklink"))
                return core::frame_producer::empty();
@@ -376,9 +377,9 @@ spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core
        auto in_format_desc = core::video_format_desc(get_param(L"FORMAT", params, L"INVALID"));
                
        if(in_format_desc.format == core::video_format::invalid)
-               in_format_desc = out_format_desc;
+               in_format_desc = dependencies.format_desc;
                        
-       return create_destroy_proxy(spl::make_shared<decklink_producer_proxy>(in_format_desc, frame_factory, out_format_desc, device_index, filter_str, length));
+       return create_destroy_proxy(spl::make_shared<decklink_producer_proxy>(in_format_desc, dependencies.frame_factory, dependencies.format_desc, device_index, filter_str, length));
 }
 
 }}
index 7b15aa6af6d1bd8e4a7431b1dd0eb288e30b0196..7e206df86c34729d9c6141a2f51556a5b489e955 100644 (file)
 
 #pragma once
 
-#include <core/producer/frame_producer.h>
+#include <core/fwd.h>
 
 #include <string>
 #include <vector>
 
 namespace caspar { namespace decklink {
        
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
+spl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params);
 
 }}
index 93deb1ddaeb2e608a0b91de5d68ad9ff76c3bd67..872905ea34d0347c5c2d507a2c77126f2cee2da5 100644 (file)
@@ -397,7 +397,7 @@ public:
        }
 };
 
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
+spl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
 {              
        auto filename = probe_stem(env::media_folder() + L"/" + params.at(0));
 
@@ -409,7 +409,7 @@ spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core
        auto length             = get_param(L"LENGTH", params, std::numeric_limits<uint32_t>::max());
        auto filter_str = get_param(L"FILTER", params, L"");    
        
-       return create_destroy_proxy(spl::make_shared_ptr(std::make_shared<ffmpeg_producer>(frame_factory, format_desc, filename, filter_str, loop, start, length)));
+       return create_destroy_proxy(spl::make_shared_ptr(std::make_shared<ffmpeg_producer>(dependencies.frame_factory, dependencies.format_desc, filename, filter_str, loop, start, length)));
 }
 
 }}
index b416492e8ca7bf14ab5400817c19786a01ef1046..b73752699cd1df23d513e3c3dcf74dd8eb52cf62 100644 (file)
 #include <common/memory.h>
 
 #include <core/fwd.h>
-#include <core/video_format.h>
 
 #include <string>
 #include <vector>
 
 namespace caspar { namespace ffmpeg {
 
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
+spl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params);
 
 }}
\ No newline at end of file
index 0a11c106076fbc3fb631cc22c41cb3db277b0902..9c6558829fe629ee3f1ed028d24dc98cc4a0ec19 100644 (file)
@@ -160,14 +160,13 @@ public:
 };
 
 spl::shared_ptr<core::frame_producer> create_ct_producer(
-               const spl::shared_ptr<core::frame_factory> frame_factory,
-               const core::video_format_desc& format_desc,
+               const core::frame_producer_dependencies& dependencies,
                const std::vector<std::wstring>& params)
 {
        if (params.empty() || !boost::filesystem::exists(get_absolute(env::media_folder(), params.at(0)) + L".ct"))
                return core::frame_producer::empty();
 
-       auto flash_producer = flash::create_producer(frame_factory, format_desc, {});
+       auto flash_producer = flash::create_producer(dependencies, {});
        auto producer = flash_producer;
        flash_cg_proxy(producer, env::media_folder()).add(0, params.at(0), true, L"", L"");
 
@@ -204,9 +203,9 @@ void init(core::module_dependencies dependencies)
                        {
                                return spl::make_shared<flash_cg_proxy>(producer);
                        },
-                       [](const spl::shared_ptr<core::frame_factory>& ff, const core::video_format_desc& f, const std::wstring&)
+                       [](const core::frame_producer_dependencies& dependencies, const std::wstring&)
                        {
-                               return flash::create_producer(ff, f, { });
+                               return flash::create_producer(dependencies, { });
                        },
                        true
                );
index dba3acb8cecd7eeafd421df7f4bb9853a6fcec92..2be1f177cdf359cfb853216823dad2fde20585a4 100644 (file)
@@ -37,6 +37,7 @@
 #include <core/frame/draw_frame.h>
 #include <core/frame/frame_factory.h>
 #include <core/frame/pixel_format.h>
+#include <core/producer/frame_producer.h>
 #include <core/monitor/monitor.h>
 
 #include <common/env.h>
@@ -499,19 +500,19 @@ public:
        }
 };
 
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
+spl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
 {
-       auto template_host = get_template_host(format_desc);
+       auto template_host = get_template_host(dependencies.format_desc);
        
        auto filename = env::template_folder() + L"\\" + template_host.filename;
        
        if(!boost::filesystem::exists(filename))
                CASPAR_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(u8(filename)));     
 
-       return create_destroy_proxy(spl::make_shared<flash_producer>(frame_factory, format_desc, filename, template_host.width, template_host.height));
+       return create_destroy_proxy(spl::make_shared<flash_producer>(dependencies.frame_factory, dependencies.format_desc, filename, template_host.width, template_host.height));
 }
 
-spl::shared_ptr<core::frame_producer> create_swf_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
+spl::shared_ptr<core::frame_producer> create_swf_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
 {
        auto filename = env::media_folder() + L"\\" + params.at(0) + L".swf";
 
@@ -521,7 +522,7 @@ spl::shared_ptr<core::frame_producer> create_swf_producer(const spl::shared_ptr<
        swf_t::header_t header(filename);
 
        return create_destroy_proxy(
-               spl::make_shared<flash_producer>(frame_factory, format_desc, filename, header.frame_width, header.frame_height));
+               spl::make_shared<flash_producer>(dependencies.frame_factory, dependencies.format_desc, filename, header.frame_width, header.frame_height));
 }
 
 std::wstring find_template(const std::wstring& template_name)
index eb0bbc3419574263da702f28b029f01e61cfb87c..6f0a9448e8a953067fc3ca8b97a4cee5d2feca0a 100644 (file)
@@ -21,7 +21,7 @@
 
 #pragma once
 
-#include <core/producer/frame_producer.h>
+#include <core/fwd.h>
 
 #include <common/memory.h>
 
@@ -30,8 +30,8 @@
 
 namespace caspar { namespace flash {
 
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
-spl::shared_ptr<core::frame_producer> create_swf_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
+spl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params);
+spl::shared_ptr<core::frame_producer> create_swf_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params);
 
 std::wstring find_template(const std::wstring& templateName);
 
index 93ee717dae99a17681b214a941743470488b6a53..9542044eaefc0cf58707cb4eff102d53ac227e37 100644 (file)
@@ -312,9 +312,9 @@ void init(core::module_dependencies dependencies)
                        {
                                return spl::make_shared<html_cg_proxy>(producer);
                        },
-                       [](const spl::shared_ptr<core::frame_factory>& ff, const core::video_format_desc& f, const std::wstring& filename)
+                       [](const core::frame_producer_dependencies& dependencies, const std::wstring& filename)
                        {
-                               return html::create_producer(ff, f, { filename });
+                               return html::create_producer(dependencies, { filename });
                        },
                        false
        );
index c8355433ef56089e21553dfce8a90779c9affa29..d9ef6c302f26124cd2edc8f08e6128595934940f 100644 (file)
@@ -454,11 +454,11 @@ namespace caspar {
                class html_producer
                        : public core::frame_producer_base
                {
-                       core::monitor::subject                          monitor_subject_;
-                       const std::wstring                                      url_;
-                       core::constraints                                       constraints_;
+                       core::monitor::subject  monitor_subject_;
+                       const std::wstring              url_;
+                       core::constraints               constraints_;
 
-                       CefRefPtr<html_client>                          client_;
+                       CefRefPtr<html_client>  client_;
 
                public:
                        html_producer(
@@ -600,8 +600,7 @@ namespace caspar {
                };
 
                spl::shared_ptr<core::frame_producer> create_producer(
-                               const spl::shared_ptr<core::frame_factory>& frame_factory,
-                               const core::video_format_desc& format_desc,
+                               const core::frame_producer_dependencies& dependencies,
                                const std::vector<std::wstring>& params)
                {
                        const auto filename = env::template_folder() + params.at(0) + L".html";
@@ -618,8 +617,8 @@ namespace caspar {
                                return core::frame_producer::empty();
 
                        return core::create_destroy_proxy(spl::make_shared<html_producer>(
-                                       frame_factory,
-                                       format_desc,
+                                       dependencies.frame_factory,
+                                       dependencies.format_desc,
                                        url));
                }
        }
index 201ff0bc184fa75a221d344ba2453cc519533b78..e753aaa574b1b544162f9115e9ac1e75c395e867 100644 (file)
@@ -31,8 +31,7 @@
 namespace caspar { namespace html {
 
 spl::shared_ptr<core::frame_producer> create_producer(
-               const spl::shared_ptr<core::frame_factory>& frame_factory,
-               const core::video_format_desc& format_desc,
+               const core::frame_producer_dependencies& dependencies,
                const std::vector<std::wstring>& params);
 
 }}
\ No newline at end of file
index f46db914d771f88c1ed301c7a232edbb1b735166..7dae24ce57ab2a96c2745e173f8f1cc4076137f8 100644 (file)
@@ -169,7 +169,7 @@ public:
        }
 };
 
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
+spl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
 {
        static const auto extensions = {
                L".png",
@@ -221,7 +221,7 @@ spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core
 
                for (auto& file : files)
                {
-                       auto frame = load_image(frame_factory, file);
+                       auto frame = load_image(dependencies.frame_factory, file);
 
                        if (width == -1)
                        {
@@ -241,7 +241,7 @@ spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core
 
                auto png_data = from_base64(std::string(params.at(1).begin(), params.at(1).end()));
 
-               return spl::make_shared<image_producer>(frame_factory, png_data.data(), png_data.size());
+               return spl::make_shared<image_producer>(dependencies.frame_factory, png_data.data(), png_data.size());
        }
 
        std::wstring filename = env::media_folder() + params.at(0);
@@ -256,12 +256,12 @@ spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core
        if(ext == extensions.end())
                return core::frame_producer::empty();
 
-       return spl::make_shared<image_producer>(frame_factory, *caspar::find_case_insensitive(filename + *ext));
+       return spl::make_shared<image_producer>(dependencies.frame_factory, *caspar::find_case_insensitive(filename + *ext));
 }
 
 
-spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
+spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
 {
-       return caspar::image::create_producer(frame_factory, format_desc, params);
+       return caspar::image::create_producer(dependencies, params);
 }
 }}
index 093094df407ce888ab99d92f0ac345f97cf1a70a..19753a21a192ba7e0a3d2e25332b0f04adea0bdf 100644 (file)
@@ -28,7 +28,7 @@
 
 namespace caspar { namespace image {
 
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
-spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
+spl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params);
+spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params);
 
 }}
\ No newline at end of file
index ffddbf9ba1e7a877702dfad62a170e4138cc2a91..35ed1aec29cdce75bc9904ea48af21ac212e1989 100644 (file)
@@ -394,7 +394,7 @@ struct image_scroll_producer : public core::frame_producer_base
        }
 };
 
-spl::shared_ptr<core::frame_producer> create_scroll_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
+spl::shared_ptr<core::frame_producer> create_scroll_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
 {
        static const auto extensions = {
                L".png",
@@ -437,8 +437,8 @@ spl::shared_ptr<core::frame_producer> create_scroll_producer(const spl::shared_p
        bool progressive = contains_param(L"PROGRESSIVE", params);
 
        return core::create_destroy_proxy(spl::make_shared<image_scroll_producer>(
-                       frame_factory,
-                       format_desc,
+                       dependencies.frame_factory,
+                       dependencies.format_desc,
                        *caspar::find_case_insensitive(filename + *ext),
                        -speed,
                        -duration,
index 7cd73de46f97db35f4ac9062fb6cf542bd1a0d14..a0f94676509ca9400e2e259437eeb9a5ea4eedfc 100644 (file)
@@ -28,6 +28,6 @@
 
 namespace caspar { namespace image {
 
-spl::shared_ptr<core::frame_producer> create_scroll_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
+spl::shared_ptr<core::frame_producer> create_scroll_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params);
 
 }}
\ No newline at end of file
index 36a6f8f06ca37d0f151af42b08bf5efcbd4f0b95..64079f002681312eaab794403c9b47c8395bd128 100644 (file)
@@ -345,7 +345,7 @@ void create_timelines(
        }
 }
 
-spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
+spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
 {
        std::wstring filename = env::template_folder() + params.at(0) + L".psd";
        auto found_file = find_case_insensitive(filename);
@@ -356,7 +356,7 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::share
        psd_document doc;
        doc.parse(*found_file);
 
-       spl::shared_ptr<core::scene::scene_producer> root(spl::make_shared<core::scene::scene_producer>(doc.width(), doc.height(), format_desc));
+       spl::shared_ptr<core::scene::scene_producer> root(spl::make_shared<core::scene::scene_producer>(doc.width(), doc.height(), dependencies.format_desc));
 
        layer_link_constructor link_constructor;
 
@@ -374,7 +374,7 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::share
                                core::text::text_info text_info(std::move(get_text_info((*it)->text_data())));
                                text_info.size *= (*it)->text_scale();
 
-                               auto text_producer = core::text_producer::create(frame_factory, 0, 0, str, text_info, doc.width(), doc.height());
+                               auto text_producer = core::text_producer::create(dependencies.frame_factory, 0, 0, str, text_info, doc.width(), doc.height());
                        
                                core::text::string_metrics metrics = text_producer->measure_string(str);
                        
@@ -385,7 +385,7 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::share
                                new_layer.hidden.set(!(*it)->is_visible());
 
                                if ((*it)->has_timeline())
-                                       create_timelines(root, format_desc, new_layer, (*it), adjustment_x, adjustment_y);
+                                       create_timelines(root, dependencies.format_desc, new_layer, (*it), adjustment_x, adjustment_y);
 
                                if((*it)->link_group_id() != 0)
                                        link_constructor.add(&new_layer, (*it)->link_group_id(), (*it)->is_position_protected(), -adjustment_x, -adjustment_y);
@@ -398,7 +398,7 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::share
                                std::shared_ptr<core::frame_producer> layer_producer;
                                if((*it)->is_solid())
                                {
-                                       layer_producer = core::create_const_producer(core::create_color_frame(it->get(), frame_factory, (*it)->solid_color().to_uint32()), (*it)->bitmap()->width(), (*it)->bitmap()->height());
+                                       layer_producer = core::create_const_producer(core::create_color_frame(it->get(), dependencies.frame_factory, (*it)->solid_color().to_uint32()), (*it)->bitmap()->width(), (*it)->bitmap()->height());
                                }
                                else if((*it)->bitmap())
                                {
@@ -413,7 +413,7 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::share
                                                core::pixel_format_desc pfd(core::pixel_format::bgra);
                                                pfd.planes.push_back(core::pixel_format_desc::plane((*it)->bitmap()->width(), (*it)->bitmap()->height(), 4));
 
-                                               auto frame = frame_factory->create_frame(it->get(), pfd);
+                                               auto frame = dependencies.frame_factory->create_frame(it->get(), pfd);
                                                memcpy(frame.image_data().data(), (*it)->bitmap()->data(), frame.image_data().size());
 
                                                layer_producer = core::create_const_producer(core::draw_frame(std::move(frame)), (*it)->bitmap()->width(), (*it)->bitmap()->height());
@@ -427,7 +427,7 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::share
                                        new_layer.hidden.set(!(*it)->is_visible());
 
                                        if ((*it)->has_timeline())
-                                               create_timelines(root, format_desc, new_layer, (*it), 0, 0);
+                                               create_timelines(root, dependencies.format_desc, new_layer, (*it), 0, 0);
 
                                        if((*it)->link_group_id() != 0)
                                                link_constructor.add(&new_layer, (*it)->link_group_id(), (*it)->is_position_protected(), 0, 0);
@@ -443,7 +443,7 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::share
                text_layer.second->text().bind(root->create_variable<std::wstring>(boost::to_lower_copy(text_layer.first), true, L""));
 
        if (doc.has_timeline())
-               create_marks(root, format_desc, doc.timeline());
+               create_marks(root, dependencies.format_desc, doc.timeline());
 
        auto params2 = params;
        params2.erase(params2.begin());
@@ -477,11 +477,10 @@ void init(core::module_dependencies dependencies)
                                return spl::make_shared<core::scene::scene_cg_proxy>(producer);
                        },
                        [](
-                                       const spl::shared_ptr<core::frame_factory>& factory,
-                                       const core::video_format_desc& format_desc,
+                                       const core::frame_producer_dependencies& dependencies,
                                        const std::wstring& filename)
                        {
-                               return create_psd_scene_producer(factory, format_desc, { filename });
+                               return create_psd_scene_producer(dependencies, { filename });
                        },
                        false);
 }
index 0a5ec82b5887b9d72e03c00cb44a01af196ba5ce..408bb41cbd0bb3d2b81bc6900a25026b1bae38a5 100644 (file)
@@ -2,13 +2,19 @@ cmake_minimum_required (VERSION 2.6)
 project (reroute)
 
 set(SOURCES
+               producer/channel_producer.cpp
+               producer/layer_producer.cpp
                producer/reroute_producer.cpp
 
+               reroute.cpp
                stdafx.cpp
 )
 set(HEADERS
+               producer/channel_producer.h
+               producer/layer_producer.h
                producer/reroute_producer.h
 
+               reroute.h
                stdafx.h
 )
 
@@ -20,9 +26,14 @@ include_directories(../..)
 include_directories(${BOOST_INCLUDE_PATH})
 include_directories(${RXCPP_INCLUDE_PATH})
 include_directories(${TBB_INCLUDE_PATH})
+include_directories(${ASMLIB_INCLUDE_PATH})
 
 set_target_properties(reroute PROPERTIES FOLDER modules)
 source_group(sources\\producer producer/*)
 source_group(sources ./*)
 
 target_link_libraries(reroute common core)
+
+casparcg_add_include_statement("modules/reroute/reroute.h")
+casparcg_add_init_statement("reroute::init" "reroute")
+casparcg_add_module_project("reroute")
diff --git a/modules/reroute/producer/channel_producer.cpp b/modules/reroute/producer/channel_producer.cpp
new file mode 100644 (file)
index 0000000..58dc2fb
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+* Copyright 2013 Sveriges Television AB http://casparcg.com/
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Robert Nagy, ronag89@gmail.com
+*/
+
+#include "../stdafx.h"
+
+#include "channel_producer.h"
+
+#include <core/monitor/monitor.h>
+#include <core/consumer/frame_consumer.h>
+#include <core/consumer/output.h>
+#include <core/producer/frame_producer.h>
+#include <core/video_channel.h>
+
+#include <core/frame/frame.h>
+#include <core/frame/pixel_format.h>
+#include <core/frame/draw_frame.h>
+#include <core/frame/frame_factory.h>
+#include <core/video_format.h>
+
+#include <boost/thread/once.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/range/algorithm/copy.hpp>
+
+#include <common/except.h>
+#include <common/memory.h>
+#include <common/future.h>
+
+#include <tbb/concurrent_queue.h>
+
+#include <asmlib.h>
+
+#include <queue>
+
+namespace caspar { namespace reroute {
+
+class channel_consumer : public core::frame_consumer
+{      
+       core::monitor::subject                                                          monitor_subject_;
+       tbb::concurrent_bounded_queue<core::const_frame>        frame_buffer_;
+       core::video_format_desc                                                         format_desc_;
+       int                                                                                                     channel_index_;
+       int                                                                                                     consumer_index_;
+       tbb::atomic<bool>                                                                       is_running_;
+       tbb::atomic<int64_t>                                                            current_age_;
+       std::promise<void>                                                                      first_frame_promise_;
+       std::future<void>                                                                       first_frame_available_;
+       bool                                                                                            first_frame_reported_;
+
+public:
+       channel_consumer()
+               : consumer_index_(next_consumer_index())
+               , first_frame_available_(first_frame_promise_.get_future())
+               , first_frame_reported_(false)
+       {
+               is_running_ = true;
+               current_age_ = 0;
+               frame_buffer_.set_capacity(3);
+       }
+
+       static int next_consumer_index()
+       {
+               static tbb::atomic<int> consumer_index_counter;
+               static boost::once_flag consumer_index_counter_initialized;
+
+               boost::call_once(consumer_index_counter_initialized, [&]()
+               {
+                       consumer_index_counter = 0;
+               });
+
+               return ++consumer_index_counter;
+       }
+
+       ~channel_consumer()
+       {
+       }
+
+       // frame_consumer
+
+       std::future<bool> send(core::const_frame frame) override
+       {
+               bool pushed = frame_buffer_.try_push(frame);
+
+               if (pushed && !first_frame_reported_)
+               {
+                       first_frame_promise_.set_value();
+                       first_frame_reported_ = true;
+               }
+
+               return make_ready_future(is_running_.load());
+       }
+
+       void initialize(
+                       const core::video_format_desc& format_desc,
+                       int channel_index) override
+       {
+               format_desc_    = format_desc;
+               channel_index_  = channel_index;
+       }
+
+       std::wstring name() const override
+       {
+               return L"channel-consumer";
+       }
+
+       std::wstring print() const override
+       {
+               return L"[channel-consumer|" + boost::lexical_cast<std::wstring>(channel_index_) + L"]";
+       }
+
+       boost::property_tree::wptree info() const override
+       {
+               boost::property_tree::wptree info;
+               info.add(L"type", L"channel-consumer");
+               info.add(L"channel-index", channel_index_);
+               return info;
+       }
+       
+       bool has_synchronization_clock() const override
+       {
+               return false;
+       }
+
+       int buffer_depth() const override
+       {
+               return -1;
+       }
+
+       int index() const override
+       {
+               return 78500 + consumer_index_;
+       }
+
+       core::monitor::subject& monitor_output() override
+       {
+               return monitor_subject_;
+       }
+
+       // channel_consumer
+       
+       const core::video_format_desc& get_video_format_desc()
+       {
+               return format_desc_;
+       }
+
+       void block_until_first_frame_available()
+       {
+               if (first_frame_available_.wait_for(std::chrono::seconds(2)) == std::future_status::timeout)
+                       CASPAR_LOG(warning)
+                                       << print() << L" Timed out while waiting for first frame";
+       }
+
+       core::const_frame receive()
+       {
+               core::const_frame frame = core::const_frame::empty();
+
+               if (!is_running_)
+                       return frame;
+               
+               frame_buffer_.try_pop(frame);
+               //if (frame_buffer_.try_pop(frame))
+//                     current_age_ = frame.get_age_millis();
+
+               return frame;
+       }
+
+       void stop()
+       {
+               is_running_ = false;
+       }
+};
+       
+class channel_producer : public core::frame_producer_base
+{
+       core::monitor::subject                                          monitor_subject_;
+
+       const spl::shared_ptr<core::frame_factory>      frame_factory_;
+       const core::video_format_desc                           output_format_desc_;
+       const spl::shared_ptr<channel_consumer>         consumer_;
+       core::constraints                                                       pixel_constraints_;
+
+       std::queue<core::draw_frame>                            frame_buffer_;
+       uint64_t                                                                        frame_number_;
+
+public:
+       explicit channel_producer(const core::frame_producer_dependencies& dependecies, const spl::shared_ptr<core::video_channel>& channel) 
+               : frame_factory_(dependecies.frame_factory)
+               , output_format_desc_(dependecies.format_desc)
+               , frame_number_(0)
+       {
+               pixel_constraints_.width.set(output_format_desc_.width);
+               pixel_constraints_.height.set(output_format_desc_.height);
+               channel->output().add(consumer_);
+               consumer_->block_until_first_frame_available();
+               CASPAR_LOG(info) << print() << L" Initialized";
+       }
+
+       ~channel_producer()
+       {
+               consumer_->stop();
+               CASPAR_LOG(info) << print() << L" Uninitialized";
+       }
+
+       // frame_producer
+                       
+       core::draw_frame receive_impl() override
+       {
+               auto format_desc = consumer_->get_video_format_desc();
+
+               if(frame_buffer_.size() > 0)
+               {
+                       auto frame = frame_buffer_.front();
+                       frame_buffer_.pop();
+                       return frame;
+               }
+               
+               auto read_frame = consumer_->receive();
+               if(read_frame == core::const_frame::empty() || read_frame.image_data().empty())
+                       return core::draw_frame::late();
+
+               frame_number_++;
+               
+               bool double_speed       = std::abs(output_format_desc_.fps / 2.0 - format_desc.fps) < 0.01;
+               bool half_speed         = std::abs(format_desc.fps / 2.0 - output_format_desc_.fps) < 0.01;
+
+               if(half_speed && frame_number_ % 2 == 0) // Skip frame
+                       return receive_impl();
+
+               core::pixel_format_desc desc;
+               desc.format = core::pixel_format::bgra;
+               desc.planes.push_back(core::pixel_format_desc::plane(format_desc.width, format_desc.height, 4));
+               auto frame = frame_factory_->create_frame(this, desc);
+
+               bool copy_audio = !double_speed && !half_speed;
+
+               if (copy_audio)
+               {
+                       frame.audio_data().reserve(read_frame.audio_data().size());
+                       boost::copy(read_frame.audio_data(), std::back_inserter(frame.audio_data()));
+               }
+
+               A_memcpy(frame.image_data().begin(), read_frame.image_data().begin(), read_frame.image_data().size());
+
+               frame_buffer_.push(core::draw_frame(std::move(frame)));
+               
+               if(double_speed)
+                       frame_buffer_.push(frame_buffer_.back());
+
+               return receive_impl();
+       }       
+
+       std::wstring name() const override
+       {
+               return L"channel-producer";
+       }
+
+       std::wstring print() const override
+       {
+               return L"channel-producer[]";
+       }
+
+       core::constraints& pixel_constraints() override
+       {
+               return pixel_constraints_;
+       }
+
+       boost::property_tree::wptree info() const override
+       {
+               boost::property_tree::wptree info;
+               info.add(L"type", L"channel-producer");
+               return info;
+       }
+
+       core::monitor::subject& monitor_output() override
+       {
+               return monitor_subject_;
+       }
+};
+
+spl::shared_ptr<core::frame_producer> create_channel_producer(
+               const core::frame_producer_dependencies& dependencies,
+               const spl::shared_ptr<core::video_channel>& channel)
+{
+       return spl::make_shared<channel_producer>(dependencies, channel);
+}
+
+}}
\ No newline at end of file
diff --git a/modules/reroute/producer/channel_producer.h b/modules/reroute/producer/channel_producer.h
new file mode 100644 (file)
index 0000000..e8faf31
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+* Copyright 2013 Sveriges Television AB http://casparcg.com/
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Robert Nagy, ronag89@gmail.com
+*/
+
+#pragma once
+
+#include <common/memory.h>
+
+#include <core/fwd.h>
+
+namespace caspar { namespace reroute {
+
+spl::shared_ptr<core::frame_producer> create_channel_producer(
+               const core::frame_producer_dependencies& dependencies,
+               const spl::shared_ptr<core::video_channel>& channel);
+
+}}
diff --git a/modules/reroute/producer/layer_producer.cpp b/modules/reroute/producer/layer_producer.cpp
new file mode 100644 (file)
index 0000000..81bf198
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Cambell Prince, cambell.prince@gmail.com
+*/
+
+#include "../stdafx.h"
+
+#include "layer_producer.h"
+
+#include <core/consumer/write_frame_consumer.h>
+#include <core/consumer/output.h>
+#include <core/video_channel.h>
+#include <core/frame/draw_frame.h>
+#include <core/frame/frame_factory.h>
+#include <core/producer/frame_producer.h>
+#include <core/producer/stage.h>
+
+#include <common/except.h>
+#include <common/future.h>
+
+#include <boost/format.hpp>
+
+#include <tbb/concurrent_queue.h>
+
+namespace caspar { namespace reroute {
+
+class layer_consumer : public core::write_frame_consumer
+{      
+       tbb::concurrent_bounded_queue<core::draw_frame> frame_buffer_;
+       std::promise<void>                                                              first_frame_promise_;
+       std::future<void>                                                               first_frame_available_;
+       bool                                                                                    first_frame_reported_;
+
+public:
+       layer_consumer()
+               : first_frame_available_(first_frame_promise_.get_future())
+               , first_frame_reported_(false)
+       {
+               frame_buffer_.set_capacity(2);
+       }
+
+       ~layer_consumer()
+       {
+       }
+
+       // write_frame_consumer
+
+       void send(const core::draw_frame& src_frame) override
+       {
+               bool pushed = frame_buffer_.try_push(src_frame);
+
+               if (pushed && !first_frame_reported_)
+               {
+                       first_frame_promise_.set_value();
+                       first_frame_reported_ = true;
+               }
+       }
+
+       std::wstring print() const override
+       {
+               return L"[layer_consumer]";
+       }
+
+       core::draw_frame receive()
+       {
+               core::draw_frame frame;
+               if (!frame_buffer_.try_pop(frame))
+               {
+                       return core::draw_frame::late();
+               }
+               return frame;
+       }
+
+       void block_until_first_frame_available()
+       {
+               if (first_frame_available_.wait_for(std::chrono::seconds(2)) == std::future_status::timeout)
+                       CASPAR_LOG(warning)
+                                       << print() << L" Timed out while waiting for first frame";
+       }
+};
+
+class layer_producer : public core::frame_producer_base
+{
+       core::monitor::subject                                          monitor_subject_;
+
+       const int                                                                       layer_;
+       const spl::shared_ptr<layer_consumer>           consumer_;
+
+       core::draw_frame                                                        last_frame_;
+       uint64_t                                                                        frame_number_;
+
+       const spl::shared_ptr<core::video_channel>      channel_;
+       core::constraints                                                       pixel_constraints_;
+
+public:
+       explicit layer_producer(const spl::shared_ptr<core::video_channel>& channel, int layer) 
+               : layer_(layer)
+               , channel_(channel)
+               , last_frame_(core::draw_frame::empty())
+               , frame_number_(0)
+       {
+               pixel_constraints_.width.set(channel->video_format_desc().width);
+               pixel_constraints_.height.set(channel->video_format_desc().height);
+               channel_->stage().add_layer_consumer(this, layer_, consumer_);
+               consumer_->block_until_first_frame_available();
+               CASPAR_LOG(info) << print() << L" Initialized";
+       }
+
+       ~layer_producer()
+       {
+               channel_->stage().remove_layer_consumer(this, layer_);
+               CASPAR_LOG(info) << print() << L" Uninitialized";
+       }
+
+       // frame_producer
+                       
+       core::draw_frame receive_impl() override
+       {
+               auto consumer_frame = consumer_->receive();
+               if (consumer_frame == core::draw_frame::late())
+                       return last_frame_;
+
+               frame_number_++;
+               return last_frame_ = consumer_frame;
+       }       
+
+       std::wstring print() const override
+       {
+               return L"layer-producer[" + boost::lexical_cast<std::wstring>(layer_) + L"]";
+       }
+
+       std::wstring name() const override
+       {
+               return L"layer-producer";
+       }
+
+       boost::property_tree::wptree info() const override
+       {
+               boost::property_tree::wptree info;
+               info.add(L"type", L"layer-producer");
+               return info;
+       }
+
+       core::monitor::subject& monitor_output() override
+       {
+               return monitor_subject_;
+       }
+
+       core::constraints& pixel_constraints() override
+       {
+               return pixel_constraints_;
+       }
+};
+
+spl::shared_ptr<core::frame_producer> create_layer_producer(const spl::shared_ptr<core::video_channel>& channel, int layer)
+{
+       return spl::make_shared<layer_producer>(channel, layer);
+}
+
+}}
\ No newline at end of file
diff --git a/modules/reroute/producer/layer_producer.h b/modules/reroute/producer/layer_producer.h
new file mode 100644 (file)
index 0000000..7f47974
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Cambell Prince, cambell.prince@gmail.com
+*/
+
+#pragma once
+
+#include <common/memory.h>
+
+#include <core/fwd.h>
+
+namespace caspar { namespace reroute {
+
+spl::shared_ptr<core::frame_producer> create_layer_producer(const spl::shared_ptr<core::video_channel>& channel, int layer);
+
+}}
index 5788c513581e64d026068b0a21a1d224759c9f16..e4095aa1b7fa8085cac39dafa34d3bcae1767159 100644 (file)
 #include "../stdafx.h"
 
 #include "reroute_producer.h"
+#include "layer_producer.h"
+#include "channel_producer.h"
 
 #include <core/producer/frame_producer.h>
-#include <core/frame/draw_frame.h>
-#include <core/frame/frame_factory.h>
-#include <core/frame/pixel_format.h>
-#include <core/frame/frame.h>
 #include <core/video_channel.h>
-#include <core/producer/stage.h>
 
-#include <common/except.h>
-#include <common/diagnostics/graph.h>
-#include <common/log.h>
-#include <common/reactive.h>
-#include <common/linq.h>
-
-#include <tbb/concurrent_queue.h>
-
-#include <boost/property_tree/ptree.hpp>
-#include <boost/optional.hpp>
-
-#include <queue>
+#include <boost/algorithm/string.hpp>
+#include <boost/range/algorithm/find_if.hpp>
 
 namespace caspar { namespace reroute {
                
-class reroute_producer : public reactive::observer<std::map<int, core::draw_frame>>
-                                          , public core::frame_producer_base
+spl::shared_ptr<core::frame_producer> create_producer(
+               const core::frame_producer_dependencies& dependencies,
+               const std::vector<std::wstring>& params)
 {
-       core::monitor::subject                                                                                  monitor_subject_;
+       static const std::wstring PREFIX = L"route://";
 
-       core::constraints                                                                                               constraints_;
-       const spl::shared_ptr<diagnostics::graph>                                               graph_;
-       
-       tbb::concurrent_bounded_queue<std::map<int, core::draw_frame>>  input_buffer_;
-public:
-       explicit reroute_producer() 
+       if (params.empty() ||
+               !boost::starts_with(params.at(0), PREFIX) ||
+               boost::ends_with(params.at(0), L"_A") ||
+               boost::ends_with(params.at(0), L"_ALPHA"))
        {
-               graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f));
-               graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));
-               graph_->set_text(print());
-               diagnostics::register_graph(graph_);
-
-               input_buffer_.set_capacity(1);
+               return core::frame_producer::empty();
        }
-               
-       // observable
 
-       void on_next(const std::map<int, core::draw_frame>& frames)
-       {
-               if(!input_buffer_.try_push(frames))
-                       graph_->set_tag("dropped-frame");               
-       }
+       auto& url = params.at(0);
+       auto channel_layer_spec = url.substr(PREFIX.length());
+       auto dash = channel_layer_spec.find(L"-");
+       bool has_layer_spec = dash != std::wstring::npos;
+       int channel_id;
 
-       // frame_producer
-                       
-       core::draw_frame receive_impl() override
-       {               
-               std::map<int, core::draw_frame> frames;
-               if(!input_buffer_.try_pop(frames))
-               {
-                       graph_->set_tag("late-frame");
-                       return core::draw_frame::late();                
-               }
+       if (has_layer_spec)
+               channel_id = boost::lexical_cast<int>(channel_layer_spec.substr(0, dash));
+       else
+               channel_id = boost::lexical_cast<int>(channel_layer_spec);
 
-               return cpplinq::from(frames)
-                       .select(values())
-                       .aggregate(core::draw_frame::empty(), core::draw_frame::over);
-       }
+       auto found_channel = boost::find_if(dependencies.channels, [=](spl::shared_ptr<core::video_channel> ch) { return ch->index() == channel_id; });
 
-       core::constraints& pixel_constraints() override
-       {
-               return constraints_;
-       }
-               
-       std::wstring print() const override
-       {
-               return L"reroute[]";
-       }
+       if (found_channel == dependencies.channels.end())
+               CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(L"No channel with id " + channel_id));
 
-       std::wstring name() const override
+       if (has_layer_spec)
        {
-               return L"reroute";
-       }
+               auto layer = boost::lexical_cast<int>(channel_layer_spec.substr(dash + 1));
 
-       boost::property_tree::wptree info() const override
-       {
-               boost::property_tree::wptree info;
-               info.add(L"type", L"rerotue-producer");
-               return info;
+               return create_layer_producer(*found_channel, layer);
        }
-               
-       core::monitor::subject& monitor_output()
+       else
        {
-               return monitor_subject_;
+               return create_channel_producer(dependencies, *found_channel);
        }
-};
-
-spl::shared_ptr<core::frame_producer> create_producer(core::video_channel& channel)
-{
-       auto producer = spl::make_shared<reroute_producer>();
-       
-       std::weak_ptr<reactive::observer<std::map<int, core::draw_frame>>> o = producer;
-
-       //channel.stage().monitor_output().link_target.subscribe(o);
-
-       return producer;
 }
 
 }}
\ No newline at end of file
index f3a00291637de849aedaaad1195672edd0d9a2c2..dc258335a28bf63a29b22ae71f8b6e85db97e7d0 100644 (file)
 
 #include <core/fwd.h>
 
+#include <vector>
+#include <string>
+
 namespace caspar { namespace reroute {
        
-spl::shared_ptr<core::frame_producer> create_producer(core::video_channel& channel);
+spl::shared_ptr<core::frame_producer> create_producer(
+               const core::frame_producer_dependencies& dependencies,
+               const std::vector<std::wstring>& params);
 
 }}
diff --git a/modules/reroute/reroute.cpp b/modules/reroute/reroute.cpp
new file mode 100644 (file)
index 0000000..d229b81
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#include "stdafx.h"
+
+#include "reroute.h"
+
+#include "producer/reroute_producer.h"
+#include <core/producer/frame_producer.h>
+
+namespace caspar { namespace reroute {
+
+void init(core::module_dependencies dependencies)
+{
+       core::register_producer_factory(reroute::create_producer);
+}
+
+}}
diff --git a/modules/reroute/reroute.h b/modules/reroute/reroute.h
new file mode 100644 (file)
index 0000000..68bbb9d
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#pragma once
+
+#include <core/module_dependencies.h>
+
+namespace caspar { namespace reroute {
+
+void init(core::module_dependencies dependencies);
+
+}}
index e77da6fce494013ea861c4fd09e3b090d83d7bcb..ebc399578fa6fc3786d160ae413aae5a6bc36cbc 100644 (file)
@@ -24,6 +24,7 @@
 #include "../util/ClientInfo.h"
 #include "amcp_shared.h"
 #include <core/consumer/frame_consumer.h>
+#include <core/producer/frame_producer.h>
 
 #include <boost/algorithm/string.hpp>
 
@@ -109,6 +110,15 @@ namespace amcp {
                AMCPChannelsAwareCommand(const AMCPChannelsAwareCommand& rhs) : channels_(rhs.channels_) {}
 
                const std::vector<channel_context>& channels() { return channels_; }
+               core::frame_producer_dependencies get_dependencies(const spl::shared_ptr<core::video_channel>& channel)
+               {
+                       return core::frame_producer_dependencies(
+                                       channel->frame_factory(),
+                                       cpplinq::from(channels())
+                                                       .select([](channel_context c) { return c.channel; })
+                                                       .to_vector(),
+                                       channel->video_format_desc());
+               }
 
        private:
                const std::vector<channel_context>& channels_;
index 4a62346576e1dd6923f7dbf1bf1f3c260706aeab..f778fd3a48fa9a7ec2fc86a94ff47d7756681735 100644 (file)
@@ -51,8 +51,6 @@
 #include <core/diagnostics/osd_graph.h>
 #include <core/system_info_provider.h>
 
-#include <modules/reroute/producer/reroute_producer.h>
-
 #include <algorithm>
 #include <locale>
 #include <fstream>
@@ -319,35 +317,19 @@ bool ChannelGridCommand::DoExecute()
                if(channel.channel != self)
                {
                        core::diagnostics::call_context::for_thread().layer = index;
-                       auto producer = reroute::create_producer(*channel.channel);
+                       auto producer = create_producer(get_dependencies(channel.channel), L"route://" + boost::lexical_cast<std::wstring>(channel.channel->index()));
                        self->stage().load(index, producer, false);
                        self->stage().play(index);
                        index++;
                }
        }
 
-       int n = channels().size()-1;
-       double delta = 1.0/static_cast<double>(n);
-       for(int x = 0; x < n; ++x)
-       {
-               for(int y = 0; y < n; ++y)
-               {
-                       int index = x+y*n+1;
-                       auto transform = [=](frame_transform transform) -> frame_transform
-                       {               
-                               transform.image_transform.fill_translation[0]   = x*delta;
-                               transform.image_transform.fill_translation[1]   = y*delta;
-                               transform.image_transform.fill_scale[0]                 = delta;
-                               transform.image_transform.fill_scale[1]                 = delta;
-                               transform.image_transform.clip_translation[0]   = x*delta;
-                               transform.image_transform.clip_translation[1]   = y*delta;
-                               transform.image_transform.clip_scale[0]                 = delta;
-                               transform.image_transform.clip_scale[1]                 = delta;                        
-                               return transform;
-                       };
-                       self->stage().apply_transform(index, transform);
-               }
-       }
+       MixerCommand mixer(client(), channels().back(), self->index(), -1);
+       auto num_channels = channels().size() - 1;
+       int square_side_length = std::ceil(std::sqrt(num_channels));
+       mixer.parameters().push_back(L"GRID");
+       mixer.parameters().push_back(boost::lexical_cast<std::wstring>(square_side_length));
+       mixer.Execute();
 
        return true;
 }
@@ -953,7 +935,7 @@ bool LoadCommand::DoExecute()
                core::diagnostics::scoped_call_context save;
                core::diagnostics::call_context::for_thread().video_channel = channel_index() + 1;
                core::diagnostics::call_context::for_thread().layer = layer_index();
-               auto pFP = create_producer(channel()->frame_factory(), channel()->video_format_desc(), parameters());
+               auto pFP = create_producer(get_dependencies(channel()), parameters());
                channel()->stage().load(layer_index(), pFP, true);
        
                SetReplyString(L"202 LOAD OK\r\n");
@@ -1018,31 +1000,18 @@ bool LoadbgCommand::DoExecute()
        //Perform loading of the clip
        try
        {
-               std::shared_ptr<core::frame_producer> pFP;
-               
-               static boost::wregex expr(LR"(\[(?<CHANNEL>\d+)\])", boost::regex::icase);
-                       
                core::diagnostics::scoped_call_context save;
                core::diagnostics::call_context::for_thread().video_channel = channel_index() + 1;
                core::diagnostics::call_context::for_thread().layer = layer_index();
 
-               boost::wsmatch what;
-               if(boost::regex_match(parameters().at(0), what, expr))
-               {
-                       auto channel_index = boost::lexical_cast<int>(what["CHANNEL"].str());
-                       pFP = reroute::create_producer(*channels().at(channel_index-1).channel); 
-               }
-               else
-               {
-                       pFP = create_producer(channel()->frame_factory(), channel()->video_format_desc(), parameters());
-               }
+               auto pFP = create_producer(get_dependencies(channel()), parameters());
                
                if(pFP == frame_producer::empty())
                        CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(parameters().size() > 0 ? parameters()[0] : L""));
 
                bool auto_play = contains_param(L"AUTO", parameters());
 
-               auto pFP2 = create_transition_producer(channel()->video_format_desc().field_mode, spl::make_shared_ptr(pFP), transitionInfo);
+               auto pFP2 = create_transition_producer(channel()->video_format_desc().field_mode, pFP, transitionInfo);
                if(auto_play)
                        channel()->stage().load(layer_index(), pFP2, false, transitionInfo.duration); // TODO: LOOP
                else
@@ -1272,7 +1241,7 @@ bool CGCommand::DoExecuteAdd() {
        }
 
        auto filename = parameters()[2];
-       auto proxy = cg_registry_->get_or_create_proxy(channel(), layer_index(core::cg_proxy::DEFAULT_LAYER), filename);
+       auto proxy = cg_registry_->get_or_create_proxy(channel(), get_dependencies(channel()), layer_index(core::cg_proxy::DEFAULT_LAYER), filename);
 
        if (proxy == core::cg_proxy::empty())
        {
index f72cba10f63f58d631612a87be9d605ce3736869..a131eb01280c8a6830a3f6f09fabad30cfea62ae 100644 (file)
@@ -113,10 +113,10 @@ private:
        bool DoExecute();
 };
 
-class LoadCommand : public AMCPChannelCommandBase<1>
+class LoadCommand : public AMCPChannelCommandBase<1>, AMCPChannelsAwareCommand
 {
 public:
-       LoadCommand(IO::ClientInfoPtr client, const channel_context& channel, unsigned int channel_index, int layer_index) : AMCPChannelCommandBase(client, channel, channel_index, layer_index)
+       LoadCommand(IO::ClientInfoPtr client, const channel_context& channel, unsigned int channel_index, int layer_index, const std::vector<channel_context>& channels) : AMCPChannelCommandBase(client, channel, channel_index, layer_index), AMCPChannelsAwareCommand(channels)
        {}
 
 private:
@@ -200,7 +200,7 @@ public:
        bool DoExecute();
 };
 
-class CGCommand : public AMCPChannelCommandBase<1>
+class CGCommand : public AMCPChannelCommandBase<1>, public AMCPChannelsAwareCommand
 {
 public:
        CGCommand(
@@ -208,8 +208,10 @@ public:
                        const channel_context& channel,
                        unsigned int channel_index,
                        int layer_index,
-                       const spl::shared_ptr<core::cg_producer_registry>& cg_registry)
+                       const spl::shared_ptr<core::cg_producer_registry>& cg_registry,
+                       const std::vector<channel_context>& channels)
                : AMCPChannelCommandBase(client, channel, channel_index, layer_index)
+               , AMCPChannelsAwareCommand(channels)
                , cg_registry_(cg_registry)
        {
        }
index f60433bd236eaaa2f7edb71e3049c312f4c90615..8faaf245b5c98bf2ac1df63e126118dc0f92277b 100644 (file)
@@ -385,7 +385,7 @@ private:
                if (     s == L"MIXER")         return std::make_shared<MixerCommand>(client, channel, channel_index, layer_index);
                else if (s == L"CALL")          return std::make_shared<CallCommand>(client, channel, channel_index, layer_index);
                else if (s == L"SWAP")          return std::make_shared<SwapCommand>(client, channel, channel_index, layer_index, channels_);
-               else if (s == L"LOAD")          return std::make_shared<LoadCommand>(client, channel, channel_index, layer_index);
+               else if (s == L"LOAD")          return std::make_shared<LoadCommand>(client, channel, channel_index, layer_index, channels_);
                else if (s == L"LOADBG")        return std::make_shared<LoadbgCommand>(client, channel, channel_index, layer_index, channels_);
                else if (s == L"ADD")           return std::make_shared<AddCommand>(client, channel, channel_index, layer_index);
                else if (s == L"REMOVE")        return std::make_shared<RemoveCommand>(client, channel, channel_index, layer_index);
@@ -394,7 +394,7 @@ private:
                else if (s == L"STOP")          return std::make_shared<StopCommand>(client, channel, channel_index, layer_index);
                else if (s == L"CLEAR")         return std::make_shared<ClearCommand>(client, channel, channel_index, layer_index);
                else if (s == L"PRINT")         return std::make_shared<PrintCommand>(client, channel, channel_index, layer_index);
-               else if (s == L"CG")            return std::make_shared<CGCommand>(client, channel, channel_index, layer_index, cg_registry_);
+               else if (s == L"CG")            return std::make_shared<CGCommand>(client, channel, channel_index, layer_index, cg_registry_, channels_);
                else if (s == L"SET")           return std::make_shared<SetCommand>(client, channel, channel_index, layer_index);
 
                return nullptr;
index e942feaf3ef7a7350f4f9a9ec1845531c9ba4672..30f24252bfdee648f067cacd56d62bcb4365efc8 100644 (file)
@@ -160,6 +160,7 @@ void MiscellaneousCommand::Execute()
                auto xmlData2 = boost::locale::conv::utf_to_utf<wchar_t, char>(std::string(xmlData_.begin(), xmlData_.end()));
                auto proxy = pCIIStrategy_->get_cg_registry()->get_or_create_proxy(
                                pCIIStrategy_->GetChannel(),
+                               pCIIStrategy_->get_dependencies(),
                                core::cg_proxy::DEFAULT_LAYER,
                                filename_);
                proxy->add(layer_, filename_, false, L"", xmlData2);
index cd0b79bd47af22f65384ee0a0211db6aba75bfb8..84a36961b7eed15691723c76d16afcc3600ede6d 100644 (file)
@@ -50,6 +50,7 @@ CIIProtocolStrategy::CIIProtocolStrategy(
                const spl::shared_ptr<core::cg_producer_registry>& cg_registry)
        : executor_(L"CIIProtocolStrategy")
        , pChannel_(channels.at(0))
+       , channels_(channels)
        , cg_registry_(cg_registry)
 {
 }
@@ -160,7 +161,7 @@ void CIIProtocolStrategy::WriteTemplateData(const std::wstring& templateName, co
        core::diagnostics::scoped_call_context save;
        core::diagnostics::call_context::for_thread().video_channel = 1;
        core::diagnostics::call_context::for_thread().layer = 0;
-       auto producer = cg_registry_->create_producer(GetChannel(), fullTemplateFilename);
+       auto producer = cg_registry_->create_producer(get_dependencies(), fullTemplateFilename);
 
        if (producer == core::frame_producer::empty())
        {
@@ -201,7 +202,7 @@ void CIIProtocolStrategy::DisplayMediaFile(const std::wstring& filename)
        core::diagnostics::call_context::for_thread().video_channel = 1;
        core::diagnostics::call_context::for_thread().layer = 0;
 
-       auto pFP = create_producer(GetChannel()->frame_factory(), GetChannel()->video_format_desc(), filename);
+       auto pFP = create_producer(get_dependencies(), filename);
        auto pTransition = create_transition_producer(GetChannel()->video_format_desc().field_mode, pFP, transition);
 
        try
index adf781828a121a0e1c365ab1b0b8c681d1dcfa97..59fe90da94a822bc85559bf7963448a2c576ae0c 100644 (file)
@@ -49,6 +49,7 @@ public:
 
        spl::shared_ptr<core::video_channel> GetChannel() const { return pChannel_; }
        spl::shared_ptr<core::cg_producer_registry> get_cg_registry() const { return cg_registry_; }
+       core::frame_producer_dependencies get_dependencies() const { return core::frame_producer_dependencies(GetChannel()->frame_factory(), channels_, GetChannel()->video_format_desc()); }
 
        void DisplayMediaFile(const std::wstring& filename);
        void DisplayTemplate(const std::wstring& titleName);
@@ -96,6 +97,7 @@ private:
        std::wstring currentProfile_;
        spl::shared_ptr<core::video_channel> pChannel_;
        spl::shared_ptr<core::cg_producer_registry> cg_registry_;
+       std::vector<spl::shared_ptr<core::video_channel>> channels_;
 };
 
 }}}
index ea559f1244404d30bf7e63eb8ff56d43a3dd0c24..409ccd11bb194b910b99d73dc5e4104c219fc157 100644 (file)
@@ -145,7 +145,7 @@ clk_protocol_strategy_factory::clk_protocol_strategy_factory(
                const std::vector<spl::shared_ptr<core::video_channel>>& channels,
                const spl::shared_ptr<core::cg_producer_registry>& cg_registry)
 {
-       add_command_handlers(command_processor_, channels.at(0), cg_registry);
+       add_command_handlers(command_processor_, channels, channels.at(0), cg_registry);
 }
 
 IO::protocol_strategy<wchar_t>::ptr clk_protocol_strategy_factory::create(
index 039a051ef13b7afb620000d8edb305feac4f81f7..130a50d3016b9e8e4177e3a0f7979f0e5ab5dd2a 100644 (file)
@@ -40,14 +40,17 @@ namespace caspar { namespace protocol { namespace CLK {
 \r
 class command_context\r
 {\r
-       bool                                                                            clock_loaded_ = false;\r
-       spl::shared_ptr<core::video_channel>            channel_;\r
-       spl::shared_ptr<core::cg_producer_registry>     cg_registry_;\r
+       bool                                                                                            clock_loaded_ = false;\r
+       std::vector<spl::shared_ptr<core::video_channel>>       channels_;\r
+       spl::shared_ptr<core::video_channel>                            channel_;\r
+       spl::shared_ptr<core::cg_producer_registry>                     cg_registry_;\r
 public:\r
        command_context(\r
+                       const std::vector<spl::shared_ptr<core::video_channel>>& channels,\r
                        const spl::shared_ptr<core::video_channel>& channel,\r
                        const spl::shared_ptr<core::cg_producer_registry>& cg_registry)\r
-               : channel_(channel)\r
+               : channels_(channels)\r
+               , channel_(channel)\r
                , cg_registry_(cg_registry)\r
        {\r
        }\r
@@ -56,7 +59,8 @@ public:
        {\r
                if (!clock_loaded_) \r
                {\r
-                       cg_registry_->get_or_create_proxy(channel_, core::cg_proxy::DEFAULT_LAYER, L"hawrysklocka/clock")->add(\r
+                       core::frame_producer_dependencies dependencies(channel_->frame_factory(), channels_, channel_->video_format_desc());\r
+                       cg_registry_->get_or_create_proxy(channel_, dependencies, core::cg_proxy::DEFAULT_LAYER, L"hawrysklocka/clock")->add(\r
                                0, L"hawrysklocka/clock", true, L"", data);\r
                        clock_loaded_ = true;\r
                }\r
@@ -153,11 +157,12 @@ clk_command_handler create_send_xml_handler(
 }\r
 \r
 void add_command_handlers(\r
-       clk_command_processor& processor, \r
+       clk_command_processor& processor,\r
+       const std::vector<spl::shared_ptr<core::video_channel>>& channels,\r
        const spl::shared_ptr<core::video_channel>& channel,\r
        const spl::shared_ptr<core::cg_producer_registry>& cg_registry)\r
 {\r
-       auto context = spl::make_shared<command_context>(channel, cg_registry);\r
+       auto context = spl::make_shared<command_context>(channels, channel, cg_registry);\r
 \r
        processor\r
                .add_handler(L"DUR", \r
index 3453b974f99d4ae4694b5051dfd06e1592141939..a4c20b204160dfa0a2ecbb231ae6c7a30fccaa8f 100644 (file)
@@ -35,7 +35,8 @@ namespace caspar { namespace protocol { namespace CLK {
  * @param channel   The channel to play the flash graphics on.\r
  */\r
 void add_command_handlers(\r
-       clk_command_processor& processor, \r
+       clk_command_processor& processor,\r
+       const std::vector<spl::shared_ptr<core::video_channel>>& channels,\r
        const spl::shared_ptr<core::video_channel>& channel,\r
        const spl::shared_ptr<core::cg_producer_registry>& cg_registry);\r
 \r