]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2: graph - Changed interface.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 5 Mar 2011 21:58:46 +0000 (21:58 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 5 Mar 2011 21:58:46 +0000 (21:58 +0000)
         channel - Change connection between stages.

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

21 files changed:
common/diagnostics/graph.cpp
common/diagnostics/graph.h
core/StdAfx.h
core/channel.cpp
core/consumer/bluefish/bluefish_consumer.cpp
core/consumer/decklink/decklink_consumer.cpp
core/consumer/oal/oal_consumer.cpp
core/consumer/ogl/ogl_consumer.cpp
core/producer/decklink/decklink_producer.cpp
core/producer/ffmpeg/ffmpeg_producer.cpp
core/producer/ffmpeg/input.cpp
core/producer/flash/flash_producer.cpp
core/producer/frame_producer_device.cpp
core/producer/frame_producer_device.h
mixer/StdAfx.h
mixer/audio/audio_mixer.cpp
mixer/frame_mixer_device.cpp
mixer/frame_mixer_device.h
protocol/StdAfx.h
shell/caspar.config
shell/shell.vcxproj

index 80d135e7f4f8baf825d4ed2b34bce8903e9febec..e4da48ea6f481a791f6bcd5d98d98d99d433d357 100644 (file)
@@ -366,11 +366,11 @@ graph::graph(const printer& parent_printer) : impl_(env::properties().get("confi
                context::register_drawable(impl_);\r
 }\r
 \r
-void graph::update(const std::string& name, float value){if(impl_)impl_->update(name, value);}\r
-void graph::set(const std::string& name, float value){if(impl_)impl_->set(name, value);}\r
-void graph::tag(const std::string& name){if(impl_)impl_->tag(name);}\r
-void graph::guide(const std::string& name, float value){if(impl_)impl_->guide(name, value);}\r
+void graph::update_value(const std::string& name, float value){if(impl_)impl_->update(name, value);}\r
+void graph::set_value(const std::string& name, float value){if(impl_)impl_->set(name, value);}\r
 void graph::set_color(const std::string& name, color c){if(impl_)impl_->set_color(name, c);}\r
+void graph::add_tag(const std::string& name){if(impl_)impl_->tag(name);}\r
+void graph::add_guide(const std::string& name, float value){if(impl_)impl_->guide(name, value);}\r
 \r
 safe_ptr<graph> create_graph(const std::string& name)\r
 {\r
index dc8aac1e64fb34d077cf6f2a9656057e9baeb302..2b5fe3f6549fb6f498d9ec684581e62a9ff069f9 100644 (file)
@@ -34,11 +34,11 @@ class graph
        graph(const std::string& name);\r
        graph(const printer& parent_printer);\r
 public:\r
-       void update(const std::string& name, float value);\r
-       void set(const std::string& name, float value);\r
-       void tag(const std::string& name);\r
-       void guide(const std::string& name, float value);\r
+       void update_value(const std::string& name, float value);\r
+       void set_value(const std::string& name, float value);\r
        void set_color(const std::string& name, color c);\r
+       void add_tag(const std::string& name);\r
+       void add_guide(const std::string& name, float value);\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index 5adedf1ec5698368bb7940fa4ab2a5f6a6d2514b..6d530d94fed4b9b359f07ca0b55938a8594e6449 100644 (file)
@@ -41,6 +41,8 @@
 #if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)\r
 #define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_\r
 \r
+#define BOOST_PARAMETER_MAX_ARITY 7\r
+\r
 #ifdef _DEBUG\r
 #include <crtdbg.h>\r
 #endif\r
@@ -69,6 +71,7 @@
 #include <boost/filesystem.hpp>\r
 #include <boost/foreach.hpp>\r
 #include <boost/range/algorithm.hpp>\r
+#include <boost/signals2.hpp>\r
 \r
 #include <GLee.h>\r
 \r
index 42f75c4980fe7232d10fa1a1e077ba16c5d5b89b..702395792b85d8bb88471ff3110854fd7720d0f4 100644 (file)
@@ -30,31 +30,26 @@ struct channel::implementation : boost::noncopyable
 {                                      \r
        const int index_;\r
        const video_format_desc format_desc_;\r
+       \r
+       const std::shared_ptr<frame_mixer_device>        mixer_;\r
+       const std::shared_ptr<frame_consumer_device> consumer_;\r
+       const std::shared_ptr<frame_producer_device> producer_;\r
 \r
-       std::shared_ptr<frame_consumer_device>  consumer_;\r
-       std::shared_ptr<frame_mixer_device>             mixer_;\r
-       std::shared_ptr<frame_producer_device>  producer_;\r
+       boost::signals2::scoped_connection mixer_connection_;\r
+       boost::signals2::scoped_connection producer_connection_;\r
 \r
 public:\r
        implementation(int index, const video_format_desc& format_desc)  \r
                : index_(index)\r
                , format_desc_(format_desc)\r
                , consumer_(new frame_consumer_device(std::bind(&implementation::print, this), format_desc))\r
-               , mixer_(new frame_mixer_device(std::bind(&implementation::print, this), format_desc, std::bind(&frame_consumer_device::send, consumer_.get(), std::placeholders::_1)))\r
-               , producer_(new frame_producer_device(std::bind(&implementation::print, this), safe_ptr<frame_factory>(mixer_), std::bind(&frame_mixer_device::send, mixer_.get(), std::placeholders::_1)))     {}\r
-\r
-       ~implementation()\r
+               , mixer_(new frame_mixer_device(std::bind(&implementation::print, this), format_desc))\r
+               , producer_(new frame_producer_device(std::bind(&implementation::print, this), safe_ptr<frame_factory>(mixer_)))        \r
        {\r
-               // Shutdown order is important! Destroy all created frames to mixer before destroying mixer.\r
-               CASPAR_LOG(info) << print() << " Shutting down channel.";\r
-               producer_.reset();\r
-               CASPAR_LOG(info) << print() << " Successfully shutdown producer-device.";\r
-               consumer_.reset();\r
-               CASPAR_LOG(info) << print() << " Successfully shutdown consumer-device.";\r
-               mixer_.reset();\r
-               CASPAR_LOG(info) << print() << " Successfully shutdown mixer-device.";\r
+               mixer_connection_ = mixer_->connect([=](const safe_ptr<const read_frame>& frame){consumer_->send(frame);});\r
+               producer_connection_ = producer_->connect([=](const std::vector<safe_ptr<draw_frame>>& frames){mixer_->send(frames);});\r
        }\r
-\r
+               \r
        std::wstring print() const\r
        {\r
                return L"channel[" + boost::lexical_cast<std::wstring>(index_+1) + L"-" +  format_desc_.name + L"]";\r
index b3ba09c6b14232272c1a0d46783558632370e57e..9a1e4f18cb771fbaa3fc8b455d6b0c88d8999713 100644 (file)
@@ -159,7 +159,7 @@ public:
                model_name_ = get_card_desc(videoCardType);\r
 \r
                graph_ = diagnostics::create_graph(narrow(print()));\r
-               graph_->guide("tick-time", 0.5);\r
+               graph_->add_guide("tick-time", 0.5);\r
                graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
                        \r
                //void* pBlueDevice = blue_attach_to_device(1);\r
@@ -314,7 +314,7 @@ public:
                                }\r
 \r
                                std::rotate(reserved_frames_.begin(), reserved_frames_.begin() + 1, reserved_frames_.end());\r
-                               graph_->update("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+                               graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
                                perf_timer_.reset();\r
                        }\r
                        catch(...)\r
index 5bf7a6550f2966bb830777262f0553baddcca892..5b4b96fa4b12e26569cb1751327541f04566661b 100644 (file)
@@ -117,7 +117,7 @@ public:
                model_name_ = std::wstring(pModelName);\r
                                \r
                graph_ = diagnostics::create_graph(narrow(print()));\r
-               graph_->guide("tick-time", 0.5);\r
+               graph_->add_guide("tick-time", 0.5);\r
                graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
                \r
                auto display_mode = get_display_mode(output_.p, format_desc_.format);\r
@@ -252,7 +252,7 @@ public:
                        CASPAR_LOG(error) << print() << L" Failed to schedule video.";\r
 \r
                std::rotate(reserved_frames_.begin(), reserved_frames_.begin() + 1, reserved_frames_.end());\r
-               graph_->update("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+               graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
                perf_timer_.reset();\r
        }\r
 \r
index 6ebffefec1abd9b39b44217b95abda1e3cc3cd30..4beef7a94bff175d6310e40d216b44170ba17160 100644 (file)
@@ -50,7 +50,7 @@ public:
                : graph_(diagnostics::create_graph(narrow(print())))\r
                , container_(5)\r
        {\r
-               graph_->guide("tick-time", 0.5);\r
+               graph_->add_guide("tick-time", 0.5);\r
                graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
                is_running_ = true;\r
        }\r
@@ -94,7 +94,7 @@ public:
                data.Samples = container_.back().data();\r
                data.NbSamples = container_.back().size();      \r
                \r
-               graph_->update("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));               \r
+               graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));         \r
                perf_timer_.reset();\r
 \r
                return is_running_;\r
index 753c0067117f1fc18d4b02f66c28982f85a0dbd6..8801458ca48effd0d27e62b3028a38501a725b81 100644 (file)
@@ -84,7 +84,7 @@ public:
                , graph_(diagnostics::create_graph(narrow(print())))\r
                , executor_(print())\r
        {               \r
-               graph_->guide("frame-time", 0.5);\r
+               graph_->add_guide("frame-time", 0.5);\r
                graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
        }\r
 \r
@@ -264,7 +264,7 @@ public:
                        while(window_.GetEvent(e)){}\r
                        render(frame);\r
                        window_.Display();\r
-                       graph_->update("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+                       graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
                });\r
        }\r
 \r
index 481125b834b16896c9e40647fdd72dcd5ce3d627..131a495288748eccc20e9742b91c87d04a86ef1c 100644 (file)
@@ -106,7 +106,7 @@ public:
                model_name_ = std::wstring(pModelName);\r
 \r
                graph_ = diagnostics::create_graph(boost::bind(&decklink_input::print, this));\r
-               graph_->guide("tick-time", 0.5);\r
+               graph_->add_guide("tick-time", 0.5);\r
                graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
                \r
                unsigned long decklinkVideoFormat = GetDecklinkVideoFormat(format_desc.format);\r
@@ -159,7 +159,7 @@ public:
        // TODO: Enable audio input\r
        virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame* video, IDeckLinkAudioInputPacket* audio)\r
        {       \r
-               graph_->update("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+               graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
                perf_timer_.reset();\r
 \r
                if(!video)\r
index 65f68c479b14919f1dbfeada75b5bdfcd3a66189..66219f24657c2fcba4970e0479e40825d598008c 100644 (file)
@@ -50,7 +50,7 @@ public:
                \r
        {\r
                graph_ = diagnostics::create_graph(boost::bind(&ffmpeg_producer::print, this)); \r
-               graph_->guide("frame-time", 0.5);\r
+               graph_->add_guide("frame-time", 0.5);\r
                graph_->set_color("frame-time",  diagnostics::color(1.0f, 0.0f, 0.0f));\r
        }\r
        \r
@@ -147,7 +147,7 @@ public:
                                return last_frame_;                     \r
                }\r
                \r
-               graph_->update("frame-time", static_cast<float>(perf_timer_.elapsed()/frame_factory_->get_video_format_desc().interval*0.5));\r
+               graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()/frame_factory_->get_video_format_desc().interval*0.5));\r
 \r
                auto result = last_frame_;\r
                if(!ouput_channel_.empty())\r
index 02aa984b3223d13ef11f6ffa97974cc60523fc2f..00071a75a710b4544d9b682c99a510a053c35fe1 100644 (file)
@@ -164,11 +164,11 @@ public:
                else if(!loop_ || !seek_frame(0, AVSEEK_FLAG_BACKWARD)) // TODO: av_seek_frame does not work for all formats\r
                        executor_.stop();\r
                else\r
-                       graph_->tag("seek");\r
+                       graph_->add_tag("seek");\r
 \r
                boost::this_thread::yield();\r
                        \r
-               graph_->update("input-buffer", static_cast<float>(video_packet_buffer_.size())/static_cast<float>(PACKET_BUFFER_COUNT));                \r
+               graph_->update_value("input-buffer", static_cast<float>(video_packet_buffer_.size())/static_cast<float>(PACKET_BUFFER_COUNT));          \r
                \r
                executor_.begin_invoke([this]{read_file();});           \r
                boost::unique_lock<boost::mutex> lock(mutex_);\r
index ca758341f859e1ffc9a8aa833ca5157e11719145..10039c4aee97cdf4d1cc77a46b070f581256d3b9 100644 (file)
@@ -91,7 +91,7 @@ public:
                , ax_(nullptr)\r
                , head_(draw_frame::empty())\r
        {\r
-               graph_->guide("frame-time", 0.5f);\r
+               graph_->add_guide("frame-time", 0.5f);\r
                graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));  \r
                graph_->set_color("param", diagnostics::color(1.0f, 0.5f, 0.0f));       \r
                graph_->set_color("underflow", diagnostics::color(0.6f, 0.3f, 0.9f));                   \r
@@ -147,7 +147,7 @@ public:
        {               \r
                if(!ax_->FlashCall(param))\r
                        CASPAR_LOG(warning) << print() << " Flash function call failed. Param: " << param << ".";\r
-               graph_->tag("param");\r
+               graph_->add_tag("param");\r
 \r
                if(abs(ax_->GetFPS() / format_desc_.fps) > 0.001)\r
                        CASPAR_LOG(warning) << print() << " Invalid frame-rate: " << ax_->GetFPS() << L". Should be either " << format_desc_.fps << L" or " << format_desc_.fps*2.0 << L".";\r
@@ -174,7 +174,7 @@ private:
        safe_ptr<draw_frame> render_simple_frame(bool underflow)\r
        {\r
                if(underflow)\r
-                       graph_->tag("underflow");\r
+                       graph_->add_tag("underflow");\r
 \r
                double frame_time = 1.0/ax_->GetFPS()*(underflow ? 0.90 : 1.0); // Reduce sync-time if in underflow.\r
                timer_.tick(frame_time); // Tick doesnt work on nested timelines, force an actual sync\r
@@ -192,7 +192,7 @@ private:
                        head_ = frame;\r
                }               \r
                \r
-               graph_->update("frame-time", static_cast<float>(perf_timer_.elapsed()/frame_time));\r
+               graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()/frame_time));\r
                return head_;\r
        }\r
 };\r
@@ -262,7 +262,7 @@ public:
                if(!renderer_)\r
                        return draw_frame::empty();\r
                \r
-               graph_->set("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));\r
+               graph_->set_value("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));\r
                if(!frame_buffer_.try_pop(tail_))\r
                        return tail_;\r
 \r
@@ -276,7 +276,7 @@ public:
                                auto frame = draw_frame::empty();\r
                                do{frame = renderer_->render_frame(frame_buffer_.size() < frame_buffer_.capacity()-2);}\r
                                while(frame_buffer_.try_push(frame) && frame == draw_frame::empty());\r
-                               graph_->set("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));    \r
+                               graph_->set_value("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));      \r
                                fps_.fetch_and_store(static_cast<int>(renderer_->fps()*100.0));\r
                        }\r
                        catch(...)\r
index 5ad3d892bb1befc7ca6353b62a27fbbddf0f03e1..292d8f6c8e35593de8267b46cf84025e0d6789bd 100644 (file)
@@ -27,29 +27,40 @@ struct frame_producer_device::implementation : boost::noncopyable
        const printer parent_printer_;\r
 \r
        std::map<int, layer> layers_;           \r
-\r
-       output_func output_;\r
-\r
+       \r
        const safe_ptr<frame_factory> factory_;\r
+\r
+       output_t output_;\r
        \r
        mutable executor executor_;\r
 public:\r
-       implementation(const printer& parent_printer, const safe_ptr<frame_factory>& factory, const output_func& output)  \r
+       implementation(const printer& parent_printer, const safe_ptr<frame_factory>& factory)  \r
                : parent_printer_(parent_printer)\r
                , factory_(factory)\r
-               , output_(output)\r
        {\r
                executor_.start();\r
-               executor_.begin_invoke([=]{tick();});\r
        }\r
 \r
        ~implementation()\r
        {\r
                CASPAR_LOG(info) << "Shutting down producer-device.";\r
        }\r
+\r
+       boost::signals2::connection connect(const output_t::slot_type& subscriber)\r
+       {\r
+               return executor_.invoke([&]() -> boost::signals2::connection\r
+               {\r
+                       if(output_.empty())\r
+                               executor_.begin_invoke([=]{tick();});           \r
+                       return output_.connect(subscriber);\r
+               });\r
+       }\r
                                        \r
        void tick()\r
-       {               \r
+       {                               \r
+               if(output_.empty())\r
+                       return;                         \r
+\r
                output_(draw());\r
                executor_.begin_invoke([=]{tick();});\r
        }\r
@@ -184,8 +195,9 @@ public:
        }\r
 };\r
 \r
-frame_producer_device::frame_producer_device(const printer& parent_printer, const safe_ptr<frame_factory>& factory, const output_func& output) : impl_(new implementation(parent_printer, factory, output)){}\r
+frame_producer_device::frame_producer_device(const printer& parent_printer, const safe_ptr<frame_factory>& factory) : impl_(new implementation(parent_printer, factory)){}\r
 frame_producer_device::frame_producer_device(frame_producer_device&& other) : impl_(std::move(other.impl_)){}\r
+boost::signals2::connection frame_producer_device::connect(const output_t::slot_type& subscriber){return impl_->connect(subscriber);}\r
 void frame_producer_device::swap(frame_producer_device& other){impl_->swap(other);}\r
 void frame_producer_device::load(int index, const safe_ptr<frame_producer>& producer, bool play_on_load, bool preview){impl_->load(index, producer, play_on_load, preview);}\r
 void frame_producer_device::pause(int index){impl_->pause(index);}\r
index 65dc584ea8783cd4b8e9319687e09373f1893c13..611ac9c94cbc47f37df00835849e2b10b3b43fe4 100644 (file)
@@ -10,6 +10,8 @@
 \r
 #include <functional>\r
 \r
+#include <boost/signals2.hpp>\r
+\r
 namespace caspar { namespace core {\r
 \r
 ////////////////////////////////////////////////////////////////////////////////////////////////////\r
@@ -26,9 +28,11 @@ namespace caspar { namespace core {
 class frame_producer_device : boost::noncopyable\r
 {\r
 public:\r
-       typedef std::function<void(const std::vector<safe_ptr<draw_frame>>&)> output_func;\r
+       typedef boost::signals2::signal<void(const std::vector<safe_ptr<draw_frame>>&)> output_t;\r
+        \r
+       boost::signals2::connection connect(const output_t::slot_type& subscriber);\r
 \r
-       explicit frame_producer_device(const printer& parent_printer, const safe_ptr<frame_factory>& factory, const output_func& output);\r
+       explicit frame_producer_device(const printer& parent_printer, const safe_ptr<frame_factory>& factory);\r
        frame_producer_device(frame_producer_device&& other);\r
        void swap(frame_producer_device& other);\r
                \r
index 7b19d3b5894a3e851c4e2fc97a77b08a67b9a029..11f3dddc2d46c8fc28b091d42639504655982001 100644 (file)
@@ -38,6 +38,8 @@
 #      endif\r
 #endif\r
 \r
+#define BOOST_PARAMETER_MAX_ARITY 7\r
+\r
 #ifdef _DEBUG\r
 #include <crtdbg.h>\r
 #endif\r
@@ -65,6 +67,7 @@
 #include <boost/filesystem.hpp>\r
 #include <boost/foreach.hpp>\r
 #include <boost/range/algorithm.hpp>\r
+#include <boost/signals2.hpp>\r
 \r
 #include <GLee.h>\r
 \r
index 0d55dd954d6717b2e306d173abdd905eb9ee1f03..6a4e6a6657624054000de1b6994e5d8335be4a86 100644 (file)
@@ -52,8 +52,8 @@ public:
                        {\r
                                for(size_t n = r.begin(); n < r.end(); ++n)\r
                                {\r
-                                       double delta = static_cast<double>(n)/static_cast<double>(audio_data_.size());\r
-                                       double sample_gain = prev_gain * (1.0 - delta) + next_gain * delta;\r
+                                       double alpha = static_cast<double>(n)/static_cast<double>(audio_data_.size());\r
+                                       double sample_gain = prev_gain * (1.0 - alpha) + next_gain * alpha;\r
                                        int sample = static_cast<int>(audio_data[n]);\r
                                        sample = (static_cast<int>(sample_gain*static_cast<double>(1<<15))*sample)>>15;\r
                                        audio_data_[n] = static_cast<short>((static_cast<int>(audio_data_[n]) + sample) & 0xFFFF);\r
index 06790ea699278cc0c02cc7a21d5c175e99328627..c6bfce7913cffe4849aa831f7ac51dcadd98eadf 100644 (file)
@@ -26,8 +26,7 @@
 #include <unordered_map>\r
 \r
 namespace caspar { namespace core {\r
-       \r
-       \r
+               \r
 template<typename T>\r
 class basic_animated_value\r
 {\r
@@ -61,14 +60,14 @@ struct frame_mixer_device::implementation : boost::noncopyable
        const printer                   parent_printer_;\r
        const video_format_desc format_desc_;\r
 \r
-       safe_ptr<diagnostics::graph> graph_;\r
+       safe_ptr<diagnostics::graph> diag_;\r
        timer perf_timer_;\r
        timer wait_perf_timer_;\r
 \r
        audio_mixer     audio_mixer_;\r
        image_mixer image_mixer_;\r
 \r
-       output_func output_;\r
+       output_t output_;\r
 \r
        std::unordered_map<int, basic_animated_value<image_transform>> image_transforms_;\r
        std::unordered_map<int, basic_animated_value<audio_transform>> audio_transforms_;\r
@@ -78,74 +77,88 @@ struct frame_mixer_device::implementation : boost::noncopyable
 \r
        executor executor_;\r
 public:\r
-       implementation(const printer& parent_printer, const video_format_desc& format_desc, const output_func& output\r
+       implementation(const printer& parent_printer, const video_format_desc& format_desc) \r
                : parent_printer_(parent_printer)\r
                , format_desc_(format_desc)\r
-               , graph_(diagnostics::create_graph(narrow(print())))\r
+               , diag_(diagnostics::create_graph(narrow(print())))\r
                , image_mixer_(format_desc)\r
-               , output_(output)\r
                , executor_(print())\r
        {\r
-               graph_->guide("frame-time", 0.5f);      \r
-               graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
-               graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
-               graph_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f));                \r
+               diag_->add_guide("frame-time", 0.5f);   \r
+               diag_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
+               diag_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
+               diag_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f));         \r
                executor_.start();\r
                executor_.set_capacity(2);\r
                CASPAR_LOG(info) << print() << L" Successfully initialized.";   \r
        }\r
-               \r
-       void send(const std::vector<safe_ptr<draw_frame>>& frames)\r
-       {                       \r
-               executor_.begin_invoke([=]\r
+\r
+       boost::signals2::connection connect(const output_t::slot_type& subscriber)\r
+       {\r
+               return output_.connect(subscriber);\r
+       }\r
+\r
+       boost::unique_future<safe_ptr<const host_buffer>> mix_image(const std::vector<safe_ptr<draw_frame>>& frames)\r
+       {\r
+               auto image = image_mixer_.begin_pass();\r
+               BOOST_FOREACH(auto& frame, frames)\r
                {\r
-                       perf_timer_.reset();\r
-                       auto image = image_mixer_.begin_pass();\r
-                       BOOST_FOREACH(auto& frame, frames)\r
+                       if(format_desc_.mode != video_mode::progressive)\r
                        {\r
-                               if(format_desc_.mode != video_mode::progressive)\r
-                               {\r
-                                       auto frame1 = make_safe<draw_frame>(frame);\r
-                                       auto frame2 = make_safe<draw_frame>(frame);\r
-\r
-                                       frame1->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
-                                       frame2->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
-\r
-                                       if(frame1->get_image_transform() != frame2->get_image_transform())\r
-                                               draw_frame::interlace(frame1, frame2, format_desc_.mode)->process_image(image_mixer_);\r
-                                       else\r
-                                               frame2->process_image(image_mixer_);\r
-                               }\r
+                               auto frame1 = make_safe<draw_frame>(frame);\r
+                               auto frame2 = make_safe<draw_frame>(frame);\r
+\r
+                               frame1->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
+                               frame2->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
+\r
+                               if(frame1->get_image_transform() != frame2->get_image_transform())\r
+                                       draw_frame::interlace(frame1, frame2, format_desc_.mode)->process_image(image_mixer_);\r
                                else\r
-                               {\r
-                                       auto frame1 = make_safe<draw_frame>(frame);\r
-                                       frame1->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
-                                       frame1->process_image(image_mixer_);\r
-                               }\r
+                                       frame2->process_image(image_mixer_);\r
                        }\r
-                       image_mixer_.end_pass();\r
-\r
-                       auto audio = audio_mixer_.begin_pass();\r
-                       BOOST_FOREACH(auto& frame, frames)\r
+                       else\r
                        {\r
-                               int num = format_desc_.mode == video_mode::progressive ? 1 : 2;\r
-\r
                                auto frame1 = make_safe<draw_frame>(frame);\r
-                               frame1->get_audio_transform() = root_audio_transform_.fetch_and_tick(num)*audio_transforms_[frame->get_layer_index()].fetch_and_tick(num);\r
-                               frame1->process_audio(audio_mixer_);\r
+                               frame1->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
+                               frame1->process_image(image_mixer_);\r
                        }\r
-                       audio_mixer_.end_pass();\r
+               }\r
+               image_mixer_.end_pass();\r
+               return std::move(image);\r
+       }\r
+\r
+       std::vector<short> mix_audio(const std::vector<safe_ptr<draw_frame>>& frames)\r
+       {\r
+               auto audio = audio_mixer_.begin_pass();\r
+               BOOST_FOREACH(auto& frame, frames)\r
+               {\r
+                       int num = format_desc_.mode == video_mode::progressive ? 1 : 2;\r
 \r
-                       graph_->update("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+                       auto frame1 = make_safe<draw_frame>(frame);\r
+                       frame1->get_audio_transform() = root_audio_transform_.fetch_and_tick(num)*audio_transforms_[frame->get_layer_index()].fetch_and_tick(num);\r
+                       frame1->process_audio(audio_mixer_);\r
+               }\r
+               audio_mixer_.end_pass();\r
+               return audio;\r
+       }\r
+               \r
+       void send(const std::vector<safe_ptr<draw_frame>>& frames)\r
+       {                       \r
+               executor_.begin_invoke([=]\r
+               {                       \r
+                       diag_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+                       perf_timer_.reset();\r
 \r
+                       auto image = mix_image(frames);\r
+                       auto audio = mix_audio(frames);\r
                        output_(make_safe<const read_frame>(std::move(image.get()), std::move(audio)));\r
 \r
-                       graph_->update("tick-time", static_cast<float>(wait_perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+                       diag_->update_value("tick-time", static_cast<float>(wait_perf_timer_.elapsed()/format_desc_.interval*0.5));\r
                        wait_perf_timer_.reset();\r
 \r
-                       graph_->set("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
+                       diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
                });\r
-               graph_->set("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
+               diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
        }\r
                \r
        safe_ptr<write_frame> create_frame(const pixel_format_desc& desc)\r
@@ -239,8 +252,9 @@ public:
        }\r
 };\r
        \r
-frame_mixer_device::frame_mixer_device(const printer& parent_printer, const video_format_desc& format_desc, const output_func& output) : impl_(new implementation(parent_printer, format_desc, output)){}\r
+frame_mixer_device::frame_mixer_device(const printer& parent_printer, const video_format_desc& format_desc) : impl_(new implementation(parent_printer, format_desc)){}\r
 frame_mixer_device::frame_mixer_device(frame_mixer_device&& other) : impl_(std::move(other.impl_)){}\r
+boost::signals2::connection frame_mixer_device::connect(const output_t::slot_type& subscriber){return impl_->connect(subscriber);}\r
 void frame_mixer_device::send(const std::vector<safe_ptr<draw_frame>>& frames){impl_->send(frames);}\r
 const video_format_desc& frame_mixer_device::get_video_format_desc() const { return impl_->format_desc_; }\r
 safe_ptr<write_frame> frame_mixer_device::create_frame(const pixel_format_desc& desc){ return impl_->create_frame(desc); }             \r
index 5b1a43e847d069cf413e348dba67544f35b25470..30287885a917af56fda63838c8b56ac1bc9f69b2 100644 (file)
@@ -32,6 +32,8 @@
 #include <common/memory/safe_ptr.h>\r
 #include <common/utility/printer.h>\r
 \r
+#include <boost/signals2.hpp>\r
+\r
 #include <functional>\r
 \r
 namespace caspar { namespace core {\r
@@ -41,9 +43,11 @@ struct video_format;
 class frame_mixer_device : public frame_factory\r
 {\r
 public:\r
-       typedef std::function<void(const safe_ptr<const read_frame>&)> output_func;\r
-\r
-       frame_mixer_device(const printer& parent_printer, const video_format_desc& format_desc, const output_func& output);\r
+       typedef boost::signals2::signal<void(const safe_ptr<const read_frame>&)> output_t;\r
+        \r
+       boost::signals2::connection connect(const output_t::slot_type& subscriber);\r
+       \r
+       frame_mixer_device(const printer& parent_printer, const video_format_desc& format_desc);\r
        frame_mixer_device(frame_mixer_device&& other); // nothrow\r
                \r
        void send(const std::vector<safe_ptr<draw_frame>>& frames); // nothrow\r
index ee02caebff81c238756b1b2dcd2146febfc8ac5c..1ef797f60a9f8d60cc59d3ae3e5a8c8fe3e63208 100644 (file)
@@ -41,6 +41,8 @@
 #if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)\r
 #define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_\r
 \r
+#define BOOST_PARAMETER_MAX_ARITY 7\r
+\r
 #ifdef _DEBUG\r
 #include <crtdbg.h>\r
 #endif\r
index b79c022d5d1eeeae2d824eaf9f5ee7ccb3c1eb9e..f3eb87ba9cc95a553b49e7b43232ff9593110e33 100644 (file)
           <windowed>true</windowed>\r
         </ogl>\r
         <audio/>\r
-        <decklink>\r
+        <!--decklink>\r
           <device>1</device>\r
           <embedded-audio>false</embedded-audio>\r
           <internal-key>false</internal-key>\r
-        </decklink>\r
+        </decklink-->\r
         <!--<bluefish>\r
           <device>1</device>\r
           <embedded-audio>true</embedded-audio>\r
index e0ffae4346ca7f8633d8ba4a180a1f00f923949f..6f0fac729ca1f31917c78b89b885bfd39c451b6f 100644 (file)
       </DataExecutionPrevention>\r
       <TargetMachine>MachineX86</TargetMachine>\r
       <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>\r
+      <MapExports>false</MapExports>\r
     </Link>\r
     <PostBuildEvent>\r
       <Command>copy $(SolutionDir)\dlls\*.dll $(OutDir)\</Command>\r
       <IgnoreSpecificDefaultLibraries>LIBC.lib</IgnoreSpecificDefaultLibraries>\r
       <GenerateDebugInformation>true</GenerateDebugInformation>\r
       <GenerateMapFile>false</GenerateMapFile>\r
-      <MapExports>true</MapExports>\r
+      <MapExports>false</MapExports>\r
       <SubSystem>Console</SubSystem>\r
       <OptimizeReferences>\r
       </OptimizeReferences>\r
       <IgnoreSpecificDefaultLibraries>LIBC.lib</IgnoreSpecificDefaultLibraries>\r
       <GenerateDebugInformation>true</GenerateDebugInformation>\r
       <GenerateMapFile>false</GenerateMapFile>\r
-      <MapExports>true</MapExports>\r
+      <MapExports>false</MapExports>\r
       <SubSystem>Console</SubSystem>\r
       <OptimizeReferences>\r
       </OptimizeReferences>\r
       <IgnoreSpecificDefaultLibraries>LIBC.lib</IgnoreSpecificDefaultLibraries>\r
       <GenerateDebugInformation>true</GenerateDebugInformation>\r
       <GenerateMapFile>false</GenerateMapFile>\r
-      <MapExports>true</MapExports>\r
+      <MapExports>false</MapExports>\r
       <SubSystem>Console</SubSystem>\r
       <OptimizeReferences>\r
       </OptimizeReferences>\r