]> git.sesse.net Git - casparcg/commitdiff
2.1.0: Started integrating monitoring from monitor-exp.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 10 Feb 2012 17:20:56 +0000 (17:20 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 10 Feb 2012 17:20:56 +0000 (17:20 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.1.0@2340 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

13 files changed:
common/reactive.h
core/consumer/output.cpp
core/consumer/output.h
core/core.vcxproj
core/core.vcxproj.filters
core/mixer/mixer.cpp
core/mixer/mixer.h
core/monitor/monitor.cpp [new file with mode: 0644]
core/monitor/monitor.h [new file with mode: 0644]
core/producer/stage.cpp
core/producer/stage.h
core/video_channel.cpp
core/video_channel.h

index cd5fd8f0e4661b59deb9b9df59fa04d63a4cf7be..8e526ff6d8d860337ceda6e7886ccc2df86cae46 100644 (file)
@@ -146,7 +146,7 @@ struct forward_func<I, I>
 \r
 }\r
 \r
-template<typename T, typename C, typename F = detail::true_func<T>>\r
+template<typename T, typename C>\r
 class observer_function : public observer<T>\r
 {\r
 public:\r
@@ -159,21 +159,13 @@ public:
        {\r
        }\r
 \r
-       observer_function(C func, F filter)\r
-               : func_(std::move(func))\r
-               , filter_(std::move(filter))\r
-       {\r
-       }\r
-\r
        observer_function(const observer_function& other)\r
                : func_(other.func_)\r
-               , filter_(other.filter_)\r
        {\r
        }\r
 \r
        observer_function(observer_function&& other)\r
                : func_(std::move(other.func_))\r
-               , filter_(std::move(other.filter_))\r
        {\r
        }\r
 \r
@@ -190,18 +182,14 @@ public:
                \r
        virtual void on_next(const T& e) override\r
        {\r
-               if(!filter_(e))\r
-                       return;\r
-\r
                func_(e);\r
        }\r
 private:\r
        C func_;\r
-       F filter_;\r
 };\r
 \r
-template<typename T, typename F>\r
-class observer_function<T, detail::void_func<T>, F> : public observer<T>\r
+template<typename T>\r
+class observer_function<T, detail::void_func<T>> : public observer<T>\r
 {\r
 public:                \r
        virtual void on_next(const T& e) override\r
@@ -209,71 +197,42 @@ public:
        }\r
 };\r
 \r
-template<typename I, typename O = I, typename F = detail::true_func<const I&>, typename T = detail::forward_func<I, O>>\r
+template<typename I, typename O = I>\r
 class basic_subject : public subject<I, O>\r
 {      \r
-    template <typename, typename, typename, typename> friend class basic_subject;\r
+    template <typename, typename> friend class basic_subject;\r
 \r
        basic_subject(const basic_subject&);\r
        basic_subject& operator=(const basic_subject&);\r
 public:        \r
        typedef typename subject<I, O>::observer                observer;\r
        typedef typename subject<I, O>::observer_ptr    observer_ptr;\r
-       typedef F                                                                               filter;\r
-       typedef T                                                                               transform;\r
 \r
        basic_subject()\r
        {\r
        }\r
-       \r
-       basic_subject(F filter)\r
-               : filter_(std::move(filter))\r
-       {\r
-       }\r
-       \r
-       basic_subject(T transform)\r
-               : transform_(std::move(transform))\r
-       {\r
-       }\r
-       \r
-       basic_subject(std::function<O(const I&)> transform)\r
-               : transform_(std::move(transform))\r
-       {\r
-       }\r
-\r
-       basic_subject(F filter, T transform)\r
-               : filter_(std::move(filter))\r
-               , transform_(std::move(transform))\r
-       {\r
-       }\r
-       \r
+                       \r
        virtual ~basic_subject()\r
        {\r
        }\r
                \r
-       template<typename F1, typename T1>\r
-       basic_subject(basic_subject<typename observer::value_type, typename observable::value_type, F1, T1>&& other)\r
+       basic_subject(basic_subject<typename observer::value_type, typename observable::value_type>&& other)\r
                : observers_(std::move(other.observers_))\r
-               , filter_(std::move(other.filter_))\r
-               , transform_(std::move(other.transform_))\r
        {\r
        }\r
        \r
-       template<typename F1, typename T1>\r
-       basic_subject& operator=(basic_subject<typename observer::value_type, typename observable::value_type, F1, T1>&& other)\r
+       basic_subject& operator=(basic_subject<typename observer::value_type, typename observable::value_type>&& other)\r
        {\r
                other.swap(*this);\r
                return *this;\r
        }\r
        \r
-       template<typename F1, typename T1>\r
-       void swap(basic_subject<typename observer::value_type, typename observable::value_type, F1, T1>& other)\r
+       void swap(basic_subject<typename observer::value_type, typename observable::value_type>& other)\r
        {               \r
                tbb::spin_rw_mutex::scoped_lock lock(mutex_, true);\r
                tbb::spin_rw_mutex::scoped_lock other_lock(other.mutex_, true);\r
 \r
                std::swap(observers_, other.observers_);\r
-               std::swap(filter_, other.filter_);              \r
        }\r
 \r
        virtual void clear()\r
@@ -309,9 +268,6 @@ public:
        \r
        virtual void on_next(const I& e) override\r
        {                               \r
-               if(!filter_(e))\r
-                       return;\r
-\r
                std::vector<spl::shared_ptr<observer>> observers;\r
 \r
                {\r
@@ -335,9 +291,8 @@ public:
                        }       \r
                }\r
                \r
-               const auto& e2 = transform_(e);\r
                for(auto it = std::begin(observers); it != std::end(observers); ++it)\r
-                       (*it)->on_next(e2);\r
+                       (*it)->on_next(e);\r
        }\r
 private:\r
        typedef tbb::cache_aligned_allocator<std::weak_ptr<observer>>   allocator;\r
@@ -345,17 +300,8 @@ private:
        std::owner_less<std::weak_ptr<observer>>                comp_;\r
        std::vector<std::weak_ptr<observer>, allocator> observers_;\r
        mutable tbb::spin_rw_mutex                                              mutex_;\r
-       F                                                                                               filter_;\r
-       T                                                                                               transform_;\r
 };\r
 \r
-template<typename F>\r
-spl::shared_ptr<basic_subject<typename std::decay<typename detail::function_traits<F>::arg1_type>::type, typename std::decay<typename detail::function_traits<F>::arg1_type>::type, F>> \r
-make_filter(F filter)\r
-{\r
-       return std::make_shared<basic_subject<std::decay<typename detail::function_traits<F>::arg1_type>::type, typename std::decay<typename detail::function_traits<F>::arg1_type>::type, F>>(std::move(filter));\r
-}\r
-\r
 template<typename F>\r
 spl::shared_ptr<observer_function<typename std::decay<typename detail::function_traits<F>::arg1_type>::type, F>> \r
 make_observer(F func)\r
@@ -363,11 +309,11 @@ make_observer(F func)
        return std::make_shared<observer_function<std::decay<typename detail::function_traits<F>::arg1_type>::type, F>>(std::move(func));\r
 }\r
 \r
-template<typename F1, typename F2>\r
-spl::shared_ptr<observer_function<typename std::decay<typename detail::function_traits<F1>::arg1_type>::type, F1, F2>> \r
-make_observer(F1 func, F2 filter)\r
+template<typename T>\r
+basic_subject<T>& operator<<(basic_subject<T>& s, const T& val)\r
 {\r
-       return std::make_shared<observer_function<std::decay<typename detail::function_traits<F1>::arg1_type>::type, F1, F2>>(std::move(func), std::move(filter));\r
+       s.on_next(val);\r
+       return s;\r
 }\r
 \r
 }}\r
@@ -380,8 +326,8 @@ void swap(caspar::reactive::observer_function<T, F1>& lhs, caspar::reactive::obs
     lhs.swap(rhs);\r
 }\r
 \r
-template <typename I, typename O, typename F1, typename F2, typename T1, typename T2>\r
-void swap(caspar::reactive::basic_subject<I, O, F1, T1>& lhs, caspar::reactive::basic_subject<I, O, F2, T2>& rhs) \r
+template <typename I, typename O>\r
+void swap(caspar::reactive::basic_subject<I, O>& lhs, caspar::reactive::basic_subject<I, O>& rhs) \r
 {\r
     lhs.swap(rhs);\r
 }\r
index ff5a51fdec2b0526c59a06bf7c676f97c93a595a..2771afb5e8e547d0153f6d3a02d99d0521bfb72d 100644 (file)
@@ -50,6 +50,7 @@ namespace caspar { namespace core {
        \r
 struct output::impl\r
 {              \r
+       spl::shared_ptr<diagnostics::graph>                                                     graph_;\r
        const int                                                                                                       channel_index_;\r
        video_format_desc                                                                                       format_desc_;\r
        std::map<int, spl::shared_ptr<frame_consumer>>                          consumers_;     \r
@@ -57,11 +58,13 @@ struct output::impl
        boost::circular_buffer<spl::shared_ptr<const data_frame>>       frames_;\r
        executor                                                                                                        executor_;              \r
 public:\r
-       impl(const video_format_desc& format_desc, int channel_index) \r
-               : channel_index_(channel_index)\r
+       impl(spl::shared_ptr<diagnostics::graph> graph, const video_format_desc& format_desc, int channel_index) \r
+               : graph_(std::move(graph))\r
+               , channel_index_(channel_index)\r
                , format_desc_(format_desc)\r
                , executor_(L"output")\r
        {\r
+               graph_->set_color("consume-time", diagnostics::color(1.0f, 0.4f, 0.0f, 0.8));\r
        }       \r
        \r
        void add(int index, spl::shared_ptr<frame_consumer> consumer)\r
@@ -101,6 +104,8 @@ public:
        {\r
                executor_.invoke([&]\r
                {\r
+                       boost::timer frame_timer;\r
+\r
                        auto it = consumers_.begin();\r
                        while(it != consumers_.end())\r
                        {                                               \r
@@ -119,6 +124,8 @@ public:
                        \r
                        format_desc_ = format_desc;\r
                        frames_.clear();\r
+\r
+                       graph_->set_value("consume-time", frame_timer.elapsed()*format_desc.fps*0.5);\r
                });\r
        }\r
 \r
@@ -200,7 +207,7 @@ public:
        }\r
 };\r
 \r
-output::output(const video_format_desc& format_desc, int channel_index) : impl_(new impl(format_desc, channel_index)){}\r
+output::output(spl::shared_ptr<diagnostics::graph> graph, const video_format_desc& format_desc, int channel_index) : impl_(new impl(std::move(graph), format_desc, channel_index)){}\r
 void output::add(int index, const spl::shared_ptr<frame_consumer>& consumer){impl_->add(index, consumer);}\r
 void output::add(const spl::shared_ptr<frame_consumer>& consumer){impl_->add(consumer);}\r
 void output::remove(int index){impl_->remove(index);}\r
index 7fda088adaf8ef670ecbaea0207ba4238a2350e4..2cfba5a1affed3913358d74e640739ee741a37cf 100644 (file)
@@ -36,7 +36,7 @@ namespace caspar { namespace core {
 class output sealed : boost::noncopyable\r
 {\r
 public:\r
-       explicit output(const struct video_format_desc& format_desc, int channel_index);\r
+       explicit output(spl::shared_ptr<diagnostics::graph> graph, const struct video_format_desc& format_desc, int channel_index);\r
        \r
        // output\r
 \r
index 27a634e50f5783cb6f7d79d9c3273d29364529a4..1703f96a967542aef92f63a6e4d05250620b2ca7 100644 (file)
     <ClInclude Include="frame\write_frame.h" />\r
     <ClInclude Include="mixer\audio\audio_util.h" />\r
     <ClInclude Include="mixer\image\blend_modes.h" />\r
+    <ClInclude Include="monitor\monitor.h" />\r
     <ClInclude Include="video_channel.h" />\r
     <ClInclude Include="consumer\output.h" />\r
     <ClInclude Include="consumer\frame_consumer.h" />\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
+    <ClCompile Include="monitor\monitor.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
     <ClCompile Include="video_channel.cpp" />\r
     <ClCompile Include="consumer\frame_consumer.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
index a0eef50ead516526976485ad088604132470e23a..125180bfc2983c805a29171ab9aa62b83698b922 100644 (file)
@@ -31,6 +31,9 @@
     <Filter Include="source\frame">\r
       <UniqueIdentifier>{b19721c1-8dd1-45fb-b9e3-212b548ebbb6}</UniqueIdentifier>\r
     </Filter>\r
+    <Filter Include="source\monitor">\r
+      <UniqueIdentifier>{e09a01c7-bfd9-4b56-97fd-ec9d060c0bbc}</UniqueIdentifier>\r
+    </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="producer\transition\transition_producer.h">\r
     <ClInclude Include="frame\write_frame.h">\r
       <Filter>source\frame</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="monitor\monitor.h">\r
+      <Filter>source\monitor</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="producer\transition\transition_producer.cpp">\r
     <ClCompile Include="frame\data_frame.cpp">\r
       <Filter>source\frame</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="monitor\monitor.cpp">\r
+      <Filter>source\monitor</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index f40f74297cdbbe1cc512da08f4e070295a7ba2ff..9a2aa78a05f452d33ad01124cf5d87ae2698ab06 100644 (file)
@@ -120,6 +120,7 @@ public:
                \r
 struct mixer::impl : boost::noncopyable\r
 {                              \r
+       spl::shared_ptr<diagnostics::graph> graph_;\r
        audio_mixer                                                     audio_mixer_;\r
        spl::shared_ptr<image_mixer>            image_mixer_;\r
        \r
@@ -128,11 +129,13 @@ struct mixer::impl : boost::noncopyable
        executor executor_;\r
 \r
 public:\r
-       impl(spl::shared_ptr<image_mixer> image_mixer) \r
-               : audio_mixer_()\r
+       impl(spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer) \r
+               : graph_(std::move(graph))\r
+               , audio_mixer_()\r
                , image_mixer_(std::move(image_mixer))\r
                , executor_(L"mixer")\r
        {                       \r
+               graph_->set_color("mix-time", diagnostics::color(1.0f, 0.0f, 0.9f, 0.8));\r
        }       \r
        \r
        spl::shared_ptr<const data_frame> operator()(std::map<int, spl::shared_ptr<draw_frame>> frames, const video_format_desc& format_desc)\r
@@ -140,7 +143,9 @@ public:
                return executor_.invoke([=]() mutable -> spl::shared_ptr<const struct data_frame>\r
                {               \r
                        try\r
-                       {                               \r
+                       {       \r
+                               boost::timer frame_timer;\r
+\r
                                BOOST_FOREACH(auto& frame, frames)\r
                                {\r
                                        auto blend_it = blend_modes_.find(frame.first);\r
@@ -154,6 +159,8 @@ public:
 \r
                                auto image = (*image_mixer_)(format_desc);\r
                                auto audio = audio_mixer_(format_desc);\r
+                               \r
+                               graph_->set_value("mix-time", frame_timer.elapsed()*format_desc.fps*0.5);\r
 \r
                                return spl::make_shared<mixed_frame>(this, std::move(image), std::move(audio), format_desc);    \r
                        }\r
@@ -185,8 +192,8 @@ public:
        }\r
 };\r
        \r
-mixer::mixer(spl::shared_ptr<image_mixer> image_mixer) \r
-       : impl_(new impl(std::move(image_mixer))){}\r
+mixer::mixer(spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer) \r
+       : impl_(new impl(std::move(graph), std::move(image_mixer))){}\r
 void mixer::set_blend_mode(int index, blend_mode value){impl_->set_blend_mode(index, value);}\r
 boost::unique_future<boost::property_tree::wptree> mixer::info() const{return impl_->info();}\r
 spl::shared_ptr<const data_frame> mixer::operator()(std::map<int, spl::shared_ptr<draw_frame>> frames, const struct video_format_desc& format_desc){return (*impl_)(std::move(frames), format_desc);}\r
index 0d4879fe8f719220d2ee5812198526d123c0b963..70b4c36785d932526b103485982e13a300596656 100644 (file)
@@ -40,7 +40,7 @@ namespace caspar { namespace core {
 class mixer sealed : boost::noncopyable\r
 {\r
 public:        \r
-       explicit mixer(spl::shared_ptr<struct image_mixer> image_mixer);\r
+       explicit mixer(spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<struct image_mixer> image_mixer);\r
                                        \r
        spl::shared_ptr<const struct data_frame> operator()(std::map<int, spl::shared_ptr<class draw_frame>> frames, const struct video_format_desc& format_desc);\r
        \r
diff --git a/core/monitor/monitor.cpp b/core/monitor/monitor.cpp
new file mode 100644 (file)
index 0000000..b258087
--- /dev/null
@@ -0,0 +1,162 @@
+#include "../StdAfx.h"\r
+\r
+#include "monitor.h"\r
+\r
+#include <utility>\r
+\r
+namespace caspar { namespace monitor {\r
+       \r
+// param\r
+       \r
+namespace detail {\r
+\r
+struct param_visitor : public boost::static_visitor<void>\r
+{\r
+       std::ostream& o;\r
+\r
+       param_visitor(std::ostream& o)\r
+               : o(o)\r
+       {\r
+       }\r
+\r
+       void operator()(const std::vector<int8_t>& bytes)\r
+       {               \r
+               o << std::string(std::begin(bytes), std::end(bytes));\r
+       }\r
+\r
+       void operator()(const duration& duration)\r
+       {               \r
+               o << duration.count();\r
+       }\r
+\r
+       template<typename T>\r
+       void operator()(const T& value)\r
+       {\r
+               o << value;\r
+       }\r
+};\r
+\r
+}\r
+\r
+std::ostream& operator<<(std::ostream& o, const param& p)\r
+{\r
+       detail::param_visitor v(o);\r
+       boost::apply_visitor(v, p);\r
+       return o;\r
+}\r
+\r
+// path\r
+\r
+path::path()\r
+{\r
+}\r
+\r
+path::path(const char* path)\r
+       : str_(path)\r
+{\r
+\r
+}\r
+\r
+path::path(std::string path)\r
+       : str_(path)\r
+{\r
+\r
+}\r
+\r
+path::path(const path& other)\r
+       : str_(other.str_)\r
+{              \r
+}\r
+       \r
+path::path(path&& other)\r
+       : str_(std::move(other.str_))\r
+{              \r
+}\r
+\r
+path& path::operator=(path other)\r
+{\r
+       std::swap(*this, other);\r
+       return *this;\r
+}\r
+\r
+path& path::operator%=(path other)\r
+{\r
+       return *this %= other.str_;\r
+}\r
+\r
+void path::swap(path& other)\r
+{\r
+       std::swap(str_, other.str_);\r
+}\r
+       \r
+const std::string& path::str() const\r
+{\r
+       return str_;\r
+}\r
+\r
+bool path::empty() const\r
+{\r
+       return str_.empty();\r
+}\r
+\r
+// event\r
+\r
+event::event(monitor::path path)\r
+       : read_only_(true)\r
+       , path_(std::move(path))\r
+       , params_(std::make_shared<params_t>())\r
+{\r
+}\r
+       \r
+event::event(monitor::path path, std::shared_ptr<params_t> params)\r
+       : read_only_(true)\r
+       , path_(std::move(path))\r
+       , params_(std::move(params))\r
+{\r
+       if(params_ == nullptr)\r
+               throw std::invalid_argument("params");\r
+}\r
+\r
+event::event(const event& other)\r
+       : read_only_(true)\r
+       , path_(other.path_)\r
+       , params_(other.params_)\r
+{\r
+}\r
+\r
+event::event(event&& other)\r
+       : read_only_(true)\r
+       , path_(std::move(other.path_))\r
+       , params_(std::move(other.params_))\r
+{\r
+}\r
+\r
+event& event::operator=(event other)\r
+{\r
+       std::swap(*this, other);\r
+       return *this;\r
+}\r
+\r
+void event::swap(event& other)\r
+{\r
+       std::swap(read_only_, other.read_only_);\r
+       std::swap(path_, other.path_);\r
+       std::swap(params_, other.params_);\r
+}\r
+               \r
+const path&    event::path() const             \r
+{\r
+       return path_;\r
+}\r
+\r
+const event::params_t& event::params() const   \r
+{\r
+       return *params_;\r
+}\r
+\r
+event event::propagate(monitor::path path) const\r
+{\r
+       return event(std::move(path) % path_, params_);\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/monitor/monitor.h b/core/monitor/monitor.h
new file mode 100644 (file)
index 0000000..f0bc33a
--- /dev/null
@@ -0,0 +1,173 @@
+#pragma once\r
+\r
+#include <common/reactive.h>\r
+#include <common/spl/memory.h>\r
+\r
+#include <functional>\r
+#include <string>\r
+#include <vector>\r
+#include <ostream>\r
+#include <type_traits>\r
+\r
+#include <boost/variant.hpp>\r
+#include <boost/lexical_cast.hpp>\r
+#include <boost/chrono.hpp>\r
+\r
+#include <tbb/cache_aligned_allocator.h>\r
+#include <tbb/spin_mutex.h>\r
+\r
+#ifndef _SCL_SECURE_NO_WARNINGS\r
+#define _SCL_SECURE_NO_WARNINGS\r
+#endif\r
+\r
+namespace caspar { namespace monitor {\r
+       \r
+// path\r
+\r
+class path sealed\r
+{\r
+public:        \r
+       path();         \r
+       path(const char* path);\r
+       path(std::string path);\r
+\r
+       path(const path& other);        \r
+       path(path&& other);\r
+               \r
+       path& operator=(path other);\r
+       path& operator%=(path other);\r
+\r
+       template<typename T>\r
+       typename std::enable_if<!std::is_same<typename std::decay<T>::type, path>::value, path&>::type operator%=(T&& value)\r
+       {\r
+               auto str = boost::lexical_cast<std::string>(std::forward<T>(value));\r
+\r
+               if(!str.empty())\r
+                       str_ += (str.front() != '/' ? "/" : "") + std::move(str);\r
+\r
+               return *this;\r
+       }\r
+\r
+       void swap(path& other);\r
+\r
+       const std::string& str() const; \r
+       bool empty() const;\r
+private:\r
+       std::string str_;\r
+};\r
+\r
+template<typename T>\r
+path operator%(path path, T&& value)\r
+{      \r
+       return std::move(path %= std::forward<T>(value));\r
+}\r
+\r
+// param\r
+\r
+typedef boost::chrono::duration<double, boost::ratio<1, 1>> duration;\r
+\r
+typedef boost::variant<bool, int32_t, int64_t, float, double, std::string, std::vector<int8_t>,  duration> param;\r
+\r
+std::ostream& operator<<(std::ostream& o, const param& p);\r
+\r
+// event\r
+\r
+class event sealed\r
+{      \r
+public:        \r
+       typedef std::vector<param, tbb::cache_aligned_allocator<param>> params_t;\r
+       \r
+       event(path path);       \r
+       event(path path, std::shared_ptr<params_t> params);     \r
+                               \r
+       event(const event& other);\r
+       event(event&& other);\r
+       event& operator=(event other);\r
+\r
+       void swap(event& other);\r
+               \r
+       template<typename T>\r
+       event& operator%(T&& value)\r
+       {\r
+               if(read_only_)\r
+               {\r
+                       read_only_ = false;\r
+                       params_ = spl::make_shared<params_t>(*params_);\r
+               }\r
+               params_->push_back(std::forward<T>(value));\r
+               return *this;\r
+       }\r
+       \r
+       event                   propagate(path path) const;\r
+       const path&             path() const;\r
+       const params_t& params() const;\r
+private:\r
+       bool                                            read_only_;             \r
+       monitor::path                           path_;\r
+       std::shared_ptr<params_t>       params_;\r
+};\r
+       \r
+class subject : public reactive::subject<monitor::event>\r
+{          \r
+       subject(const subject&);\r
+       subject& operator=(const subject&);\r
+       \r
+       typedef reactive::basic_subject<monitor::event> impl;\r
+public:                \r
+       subject(monitor::path path = monitor::path())\r
+               : path_(std::move(path))\r
+               , impl_(std::make_shared<impl>())\r
+\r
+       {\r
+       }\r
+               \r
+       subject(subject&& other)\r
+               : path_(std::move(other.path_))\r
+               , impl_(std::move(other.impl_))\r
+       {\r
+       }\r
+\r
+       virtual ~subject()\r
+       {\r
+       }\r
+       \r
+       virtual void subscribe(const observer_ptr& o) override\r
+       {                               \r
+               impl_->subscribe(o);\r
+       }\r
+\r
+       virtual void unsubscribe(const observer_ptr& o) override\r
+       {\r
+               impl_->unsubscribe(o);\r
+       }\r
+                               \r
+       virtual void on_next(const monitor::event& e) override\r
+       {                               \r
+               impl_->on_next(path_.empty() ? e : e.propagate(path_));\r
+       }\r
+private:\r
+       monitor::path                   path_;\r
+       std::shared_ptr<impl>   impl_;\r
+};\r
+\r
+inline subject& operator<<(subject& s, const event& e)\r
+{\r
+       s.on_next(e);\r
+       return s;\r
+}\r
+\r
+}}\r
+\r
+namespace std {\r
+\r
+inline void swap(caspar::monitor::path& lhs, caspar::monitor::path& rhs) \r
+{\r
+    lhs.swap(rhs);\r
+}\r
+   \r
+inline void swap(caspar::monitor::event& lhs, caspar::monitor::event& rhs) \r
+{\r
+    lhs.swap(rhs);\r
+}\r
+\r
+}\r
index 15ec46615d0eeab571267cd83974b22f07affdaa..4d6c426f23b0aeccd2baacafb3525a3c096b58da 100644 (file)
 namespace caspar { namespace core {\r
        \r
 struct stage::impl : public std::enable_shared_from_this<impl>\r
-{                      \r
+{                              \r
+       spl::shared_ptr<diagnostics::graph> graph_;\r
        std::map<int, layer>                            layers_;        \r
        std::map<int, tweened_transform>        tweens_;        \r
        executor                                                        executor_;\r
 public:\r
-       impl() : executor_(L"stage")\r
+       impl(spl::shared_ptr<diagnostics::graph> graph) \r
+               : graph_(std::move(graph))\r
+               , executor_(L"stage")\r
        {\r
+               graph_->set_color("produce-time", diagnostics::color(0.0f, 1.0f, 0.0f));\r
        }\r
                \r
        std::map<int, spl::shared_ptr<draw_frame>> operator()(const struct video_format_desc& format_desc)\r
        {               \r
                return executor_.invoke([=]() -> std::map<int, spl::shared_ptr<draw_frame>>\r
                {\r
+                       boost::timer frame_timer;\r
+\r
                        std::map<int, spl::shared_ptr<class draw_frame>> frames;\r
 \r
                        try\r
@@ -103,6 +109,8 @@ public:
                                layers_.clear();\r
                                CASPAR_LOG_CURRENT_EXCEPTION();\r
                        }       \r
+                       \r
+                       graph_->set_value("produce-time", frame_timer.elapsed()*format_desc.fps*0.5);\r
 \r
                        return frames;\r
                });\r
@@ -272,7 +280,7 @@ public:
        }               \r
 };\r
 \r
-stage::stage() : impl_(new impl()){}\r
+stage::stage(spl::shared_ptr<diagnostics::graph> graph) : impl_(new impl(std::move(graph))){}\r
 void stage::apply_transforms(const std::vector<stage::transform_tuple_t>& transforms){impl_->apply_transforms(transforms);}\r
 void stage::apply_transform(int index, const std::function<core::frame_transform(core::frame_transform)>& transform, unsigned int mix_duration, const tweener& tween){impl_->apply_transform(index, transform, mix_duration, tween);}\r
 void stage::clear_transforms(int index){impl_->clear_transforms(index);}\r
index 02d70467905a525eefaef46924f0be652925b9f1..192fcb524341eeb46047506dc5f89f1ec18ef123 100644 (file)
@@ -47,7 +47,7 @@ public:
        typedef std::function<struct frame_transform(struct frame_transform)> transform_func_t;\r
        typedef std::tuple<int, transform_func_t, unsigned int, tweener> transform_tuple_t;\r
 \r
-       stage();\r
+       stage(spl::shared_ptr<diagnostics::graph> graph);\r
                \r
        std::map<int, spl::shared_ptr<class draw_frame>> operator()(const struct video_format_desc& format_desc);\r
 \r
index fd6f29711bad2763140a78c14cd8adea16e3c48c..c823a96bed5998c082328d9be745802af1cadd3b 100644 (file)
@@ -47,6 +47,7 @@ namespace caspar { namespace core {
 struct video_channel::impl sealed : public frame_factory\r
 {\r
        reactive::basic_subject<spl::shared_ptr<const data_frame>> frame_subject_;\r
+       monitor::subject                                                                                   event_subject_;\r
 \r
        const int                                                                               index_;\r
 \r
@@ -59,25 +60,18 @@ struct video_channel::impl sealed : public frame_factory
        const spl::shared_ptr<caspar::core::mixer>              mixer_;\r
        const spl::shared_ptr<caspar::core::stage>              stage_; \r
 \r
-       boost::timer                                                                    tick_timer_;\r
-       boost::timer                                                                    produce_timer_;\r
-       boost::timer                                                                    mix_timer_;\r
-       boost::timer                                                                    consume_timer_;\r
-\r
        executor                                                                                executor_;\r
 public:\r
        impl(int index, const video_format_desc& format_desc, spl::shared_ptr<image_mixer> image_mixer)  \r
-               :  index_(index)\r
+               : event_subject_(monitor::path() % "channel" % index)\r
+               , index_(index)\r
                , format_desc_(format_desc)\r
-               , output_(new caspar::core::output(format_desc, index))\r
-               , mixer_(new caspar::core::mixer(std::move(image_mixer)))\r
-               , stage_(new caspar::core::stage())     \r
+               , output_(new caspar::core::output(graph_, format_desc, index))\r
+               , mixer_(new caspar::core::mixer(graph_, std::move(image_mixer)))\r
+               , stage_(new caspar::core::stage(graph_))       \r
                , executor_(L"video_channel")\r
        {\r
-               //graph_->set_color("mix-time", diagnostics::color(1.0f, 0.0f, 0.9f, 0.8));\r
-               graph_->set_color("produce-time", diagnostics::color(0.0f, 1.0f, 0.0f));\r
                graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));   \r
-               graph_->set_color("consume-time", diagnostics::color(1.0f, 0.4f, 0.0f, 0.8));\r
                graph_->set_text(print());\r
                diagnostics::register_graph(graph_);\r
 \r
@@ -107,35 +101,26 @@ public:
        {\r
                try\r
                {\r
-                       tick_timer_.restart();\r
+                       boost::timer frame_timer;\r
 \r
                        // Produce\r
-\r
-                       produce_timer_.restart();\r
-\r
+                       \r
                        auto stage_frames = (*stage_)(format_desc_);\r
-               \r
-                       graph_->set_value("produce-time", produce_timer_.elapsed()*format_desc_.fps*0.5);\r
 \r
                        // Mix\r
-\r
-                       //mix_timer_.restart();\r
-\r
+                       \r
                        auto mixed_frame  = (*mixer_)(std::move(stage_frames), format_desc_);\r
-               \r
-                       //graph_->set_value("mix-time", mix_timer_.elapsed()*format_desc_.fps*0.5);\r
 \r
                        // Consume\r
-\r
-                       consume_timer_.restart();\r
-\r
-                       frame_subject_.on_next(mixed_frame);\r
-\r
-                       graph_->set_value("consume-time", consume_timer_.elapsed()*format_desc_.fps*0.5);\r
-\r
+                       \r
+                       frame_subject_ << mixed_frame;\r
+                       \r
                        (*output_)(std::move(mixed_frame), format_desc_);\r
                \r
-                       graph_->set_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);\r
+                       graph_->set_value("tick-time", frame_timer.elapsed()*format_desc_.fps*0.5);\r
+\r
+                       event_subject_ << monitor::event("debug/time") % frame_timer.elapsed();\r
+                       event_subject_ << monitor::event("format");\r
                }\r
                catch(...)\r
                {\r
@@ -183,7 +168,9 @@ spl::shared_ptr<output> video_channel::output() { return impl_->output_;}
 video_format_desc video_channel::get_video_format_desc() const{return impl_->format_desc_;}\r
 void video_channel::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
 boost::property_tree::wptree video_channel::info() const{return impl_->info();}\r
-void video_channel::subscribe(const observer_ptr& o) {impl_->frame_subject_.subscribe(o);}\r
-void video_channel::unsubscribe(const observer_ptr& o) {impl_->frame_subject_.unsubscribe(o);}\r
+void video_channel::subscribe(const frame_observer::observer_ptr& o) {impl_->frame_subject_.subscribe(o);}\r
+void video_channel::unsubscribe(const frame_observer::observer_ptr& o) {impl_->frame_subject_.unsubscribe(o);}         \r
+void video_channel::subscribe(const event_observer::observer_ptr& o) {impl_->event_subject_.subscribe(o);}\r
+void video_channel::unsubscribe(const event_observer::observer_ptr& o) {impl_->event_subject_.unsubscribe(o);}\r
 \r
 }}
\ No newline at end of file
index ab2308d744fe6acd66ff56fb7bb17662ab885371..8255160f8eb1b8b09bcfe4a8ccaa280e691ad2ea 100644 (file)
 #include <common/reactive.h>\r
 #include <common/forward.h>\r
 \r
+#include "monitor/monitor.h"\r
+\r
 #include <boost/property_tree/ptree_fwd.hpp>\r
 \r
 FORWARD3(caspar, core, ogl, class accelerator);\r
 \r
 namespace caspar { namespace core {\r
        \r
-class video_channel sealed : public reactive::observable<spl::shared_ptr<const struct data_frame>>\r
+typedef reactive::observable<spl::shared_ptr<const struct data_frame>> frame_observer;\r
+typedef reactive::observable<monitor::event>                                                   event_observer;\r
+\r
+class video_channel sealed : public frame_observer\r
+                                                  , public event_observer\r
 {\r
        video_channel(const video_channel&);\r
        video_channel& operator=(const video_channel&);\r
@@ -48,10 +54,13 @@ public:
        \r
        boost::property_tree::wptree info() const;\r
 \r
-       // observable\r
+       // observable<spl::shared_ptr<const struct data_frame>>\r
        \r
-       virtual void subscribe(const observer_ptr& o) override;\r
-       virtual void unsubscribe(const observer_ptr& o) override;\r
+       virtual void subscribe(const frame_observer::observer_ptr& o) override;\r
+       virtual void unsubscribe(const frame_observer::observer_ptr& o) override;\r
+               \r
+       virtual void subscribe(const event_observer::observer_ptr& o) override;\r
+       virtual void unsubscribe(const event_observer::observer_ptr& o) override;\r
 private:\r
        struct impl;\r
        spl::shared_ptr<impl> impl_;\r