]> git.sesse.net Git - casparcg/commitdiff
2.1.0: -reroute: WIP.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 24 Mar 2012 18:21:45 +0000 (18:21 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 24 Mar 2012 18:21:45 +0000 (18:21 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.1.0@2733 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

core/producer/stage.cpp
core/producer/stage.h
modules/reroute/producer/reroute_producer.cpp
modules/reroute/producer/reroute_producer.h
protocol/amcp/AMCPCommandsImpl.cpp
protocol/amcp/AMCPProtocolStrategy.cpp
shell/casparcg.config

index 517036f7947d9fb1c9e2eb5d7ab338ba74539949..b1ed3461d5e1e20cf9bb240f3e2136ae5b3db56a 100644 (file)
@@ -49,11 +49,12 @@ namespace caspar { namespace core {
        \r
 struct stage::impl : public std::enable_shared_from_this<impl>\r
 {                              \r
-       spl::shared_ptr<diagnostics::graph> graph_;\r
-       monitor::basic_subject                          event_subject_;\r
-       std::map<int, layer>                            layers_;        \r
-       std::map<int, tweened_transform>        tweens_;        \r
-       executor                                                        executor_;\r
+       spl::shared_ptr<diagnostics::graph>                                                     graph_;\r
+       monitor::basic_subject                                                                          event_subject_;\r
+       reactive::basic_subject<std::map<int, class draw_frame>>        frames_subject_;\r
+       std::map<int, layer>                                                                            layers_;        \r
+       std::map<int, tweened_transform>                                                        tweens_;        \r
+       executor                                                                                                        executor_;\r
 public:\r
        impl(spl::shared_ptr<diagnostics::graph> graph) \r
                : graph_(std::move(graph))\r
@@ -65,7 +66,7 @@ public:
                \r
        std::map<int, draw_frame> operator()(const struct video_format_desc& format_desc)\r
        {               \r
-               return executor_.invoke([=]() -> std::map<int, draw_frame>\r
+               auto frames = executor_.invoke([=]() -> std::map<int, draw_frame>\r
                {\r
                        boost::timer frame_timer;\r
 \r
@@ -95,6 +96,9 @@ public:
 \r
                        return frames;\r
                });\r
+               \r
+               frames_subject_ << frames;\r
+               return frames;\r
        }\r
 \r
        void draw(int index, const video_format_desc& format_desc, std::map<int, draw_frame>& frames)\r
@@ -351,4 +355,6 @@ boost::unique_future<boost::property_tree::wptree> stage::info(int index) const{
 std::map<int, class draw_frame> stage::operator()(const video_format_desc& format_desc){return (*impl_)(format_desc);}\r
 void stage::subscribe(const monitor::observable::observer_ptr& o) {impl_->event_subject_.subscribe(o);}\r
 void stage::unsubscribe(const monitor::observable::observer_ptr& o) {impl_->event_subject_.unsubscribe(o);}\r
+void stage::subscribe(const frame_observable::observer_ptr& o) {impl_->frames_subject_.subscribe(o);}\r
+void stage::unsubscribe(const frame_observable::observer_ptr& o) {impl_->frames_subject_.unsubscribe(o);}\r
 }}
\ No newline at end of file
index e07c71b85e16fb8ee261e392d0832142e6707b6b..9a60b192cc1dee7e15f7da959a864bd67a0ed759 100644 (file)
 #include <boost/property_tree/ptree_fwd.hpp>\r
 \r
 #include <functional>\r
+#include <map>\r
 #include <tuple>\r
 #include <vector>\r
 \r
 FORWARD2(caspar, diagnostics, class graph);\r
 \r
 namespace caspar { namespace core {\r
+\r
+typedef reactive::observable<std::map<int, class draw_frame>> frame_observable;\r
        \r
-class stage sealed : public monitor::observable\r
+class stage sealed : public monitor::observable, public frame_observable\r
 {\r
        stage(const stage&);\r
        stage& operator=(const stage&);\r
@@ -79,6 +82,11 @@ public:
 \r
        void subscribe(const monitor::observable::observer_ptr& o) override;\r
        void unsubscribe(const monitor::observable::observer_ptr& o) override;\r
+       \r
+       // frame_observable\r
+\r
+       void subscribe(const frame_observable::observer_ptr& o) override;\r
+       void unsubscribe(const frame_observable::observer_ptr& o) override;\r
 \r
        // Properties\r
 \r
index e31c00983de429f2f20be2d3f4b39d8a68e7d833..80dc1f128fd82716e6c491f5ca4fdfe8f2210f13 100644 (file)
@@ -28,6 +28,8 @@
 #include <core/frame/frame_factory.h>\r
 #include <core/frame/pixel_format.h>\r
 #include <core/frame/frame.h>\r
+#include <core/video_channel.h>\r
+#include <core/producer/stage.h>\r
 \r
 #include <common/except.h>\r
 #include <common/diagnostics/graph.h>\r
 #include <tbb/concurrent_queue.h>\r
 \r
 #include <boost/property_tree/ptree.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/optional.hpp>\r
 #include <boost/range/algorithm_ext/push_back.hpp>\r
+#include <boost/range/numeric.hpp>\r
+#include <boost/range/adaptor/map.hpp>\r
 \r
 #include <queue>\r
 \r
 namespace caspar { namespace reroute {\r
-//             \r
-//class reroute_producer : public reactive::observer<spl::shared_ptr<const core::frame>>\r
-//                                        , public core::frame_producer\r
-//{\r
-//     const spl::shared_ptr<diagnostics::graph>                                                                       graph_;\r
-//     const spl::shared_ptr<core::frame_factory>                                                                      frame_factory_;\r
-//     \r
-//     tbb::concurrent_bounded_queue<std::shared_ptr<const core::frame>>               input_buffer_;\r
-//     std::queue<core::draw_frame>                                                                                            frame_buffer_;\r
-//     uint64_t                                                                                                                                        frame_number_;\r
-//\r
-//     core::draw_frame                                                                                                                        last_frame_;\r
-//\r
-//public:\r
-//     explicit reroute_producer(const spl::shared_ptr<core::frame_factory>& frame_factory) \r
-//             : frame_factory_(frame_factory)\r
-//             , frame_number_(0)\r
-//             , last_frame_(core::draw_frame::empty())\r
-//     {\r
-//             graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f));\r
-//             graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
-//             graph_->set_text(print());\r
-//             diagnostics::register_graph(graph_);\r
-//\r
-//             input_buffer_.set_capacity(1);\r
-//     }\r
-//     \r
-//     // observable\r
-//\r
-//     void on_next(const spl::shared_ptr<const core::frame>& frame)\r
-//     {\r
-//             if(!input_buffer_.try_push(frame))\r
-//                     graph_->set_tag("dropped-frame");\r
-//     }\r
-//\r
-//     // frame_producer\r
-//                     \r
-//     core::draw_frame receive(int) override\r
-//     {\r
-//             if(!frame_buffer_.empty())\r
-//             {\r
-//                     auto frame = std::move(frame_buffer_.front());\r
-//                     frame_buffer_.pop();\r
-//                     return last_frame_ = frame;\r
-//             }\r
-//             \r
-//             std::shared_ptr<const core::frame> read_frame;\r
-//             if(!input_buffer_.try_pop(read_frame))\r
-//             {\r
-//                     graph_->set_tag("late-frame");\r
-//                     return core::draw_frame::late();                \r
-//             }\r
-//             \r
-//             frame_number_++;\r
-//             \r
-//             bool double_speed       = std::abs(frame_factory_->video_format_desc().fps / 2.0 - read_frame->frame_rate()) < 0.01;            \r
-//             bool half_speed         = std::abs(read_frame->frame_rate() / 2.0 - frame_factory_->video_format_desc().fps) < 0.01;\r
-//\r
-//             if(half_speed && frame_number_ % 2 == 0) // Skip frame\r
-//                     return receive(0);\r
-//\r
-//             auto frame = frame_factory_->create_frame(this, read_frame->pixel_format_desc());\r
-//\r
-//             A_memcpy(frame->image_data(0).begin(), read_frame->image_data().begin(), read_frame->image_data().size());\r
-//             boost::push_back(frame->audio_data(), read_frame->audio_data());\r
-//             \r
-//             auto draw_frame = core::draw_frame(std::move(frame));\r
-//\r
-//             frame_buffer_.push(draw_frame);\r
-//             \r
-//             if(double_speed)        \r
-//                     frame_buffer_.push(draw_frame);\r
-//\r
-//             return receive(0);\r
-//     }       \r
-//\r
-//     core::draw_frame last_frame() const override\r
-//     {\r
-//             return core::draw_frame::still(last_frame_);\r
-//     }\r
-//     \r
-//     std::wstring print() const override\r
-//     {\r
-//             return L"reroute[]";\r
-//     }\r
-//\r
-//     std::wstring name() const override\r
-//     {\r
-//             return L"reroute";\r
-//     }\r
-//\r
-//     boost::property_tree::wptree info() const override\r
-//     {\r
-//             boost::property_tree::wptree info;\r
-//             info.add(L"type", L"rerotue-producer");\r
-//             return info;\r
-//     }\r
-//};\r
-\r
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, core::video_channel& channel)\r
+               \r
+class reroute_producer : public reactive::observer<std::map<int, core::draw_frame>>\r
+                                          , public core::frame_producer_base\r
 {\r
-       BOOST_THROW_EXCEPTION(not_implemented());\r
-       //return core::frame_producer::empty();\r
-       //auto producer = spl::make_shared<reroute_producer>(frame_factory);\r
-       //o.subscribe(producer);\r
-       //return core::wrap_producer(producer);\r
+       const spl::shared_ptr<diagnostics::graph>                                               graph_;\r
+       \r
+       tbb::concurrent_bounded_queue<std::map<int, core::draw_frame>>  input_buffer_;\r
+public:\r
+       explicit reroute_producer() \r
+       {\r
+               graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f));\r
+               graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
+               graph_->set_text(print());\r
+               diagnostics::register_graph(graph_);\r
+\r
+               input_buffer_.set_capacity(1);\r
+       }\r
+               \r
+       // observable\r
+\r
+       void on_next(const std::map<int, core::draw_frame>& frames)\r
+       {\r
+               if(!input_buffer_.try_push(frames))\r
+               {\r
+                       std::map<int, core::draw_frame> dummy;\r
+                       input_buffer_.try_pop(dummy);\r
+                       input_buffer_.try_push(frames);\r
+\r
+                       graph_->set_tag("dropped-frame");\r
+               }\r
+       }\r
+\r
+       // frame_producer\r
+                       \r
+       core::draw_frame receive_impl() override\r
+       {               \r
+               std::map<int, core::draw_frame> frames;\r
+               if(!input_buffer_.try_pop(frames))\r
+               {\r
+                       graph_->set_tag("late-frame");\r
+                       return core::draw_frame::late();                \r
+               }\r
+\r
+               return boost::accumulate(frames | boost::adaptors::map_values, core::draw_frame::empty(), core::draw_frame::over);\r
+       }       \r
+               \r
+       std::wstring print() const override\r
+       {\r
+               return L"reroute[]";\r
+       }\r
+\r
+       std::wstring name() const override\r
+       {\r
+               return L"reroute";\r
+       }\r
+\r
+       boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"rerotue-producer");\r
+               return info;\r
+       }\r
+               \r
+       void subscribe(const monitor::observable::observer_ptr& o) override\r
+       {\r
+       }\r
+\r
+       void unsubscribe(const monitor::observable::observer_ptr& o) override\r
+       {\r
+       }\r
+};\r
+\r
+spl::shared_ptr<core::frame_producer> create_producer(core::video_channel& channel)\r
+{\r
+       auto producer = spl::make_shared<reroute_producer>();\r
+       \r
+       std::weak_ptr<reactive::observer<std::map<int, core::draw_frame>>> o = producer;\r
+\r
+       channel.stage().subscribe(o);\r
+\r
+       return producer;\r
 }\r
 \r
 }}
\ No newline at end of file
index 4971b844caa38546138a092662558a71f288d9e6..3a99bae89dbca7bb11f319a6db311e3b4603fd91 100644 (file)
 \r
 #include <common/memory.h>\r
 #include <common/forward.h>\r
-\r
-#include <core/frame/frame_factory.h>\r
-#include <core/producer/frame_producer.h>\r
-#include <core/frame/frame.h>\r
+#include <common/reactive.h>\r
 \r
 FORWARD2(caspar, core, class video_channel);\r
+FORWARD2(caspar, core, class frame_producer);\r
 \r
 namespace caspar { namespace reroute {\r
        \r
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, core::video_channel& channel);\r
+spl::shared_ptr<core::frame_producer> create_producer(core::video_channel& channel);\r
 \r
 }}\r
index 38a87675c2df39b9170dc4297470a76d2b959a2c..5be1aa4294f7300d943ddc39e40e6fa54c5433e4 100644 (file)
@@ -44,6 +44,7 @@
 #include <core/mixer/mixer.h>\r
 #include <core/consumer/output.h>\r
 \r
+#include <modules/reroute/producer/reroute_producer.h>\r
 #include <modules/bluefish/bluefish.h>\r
 #include <modules/decklink/decklink.h>\r
 #include <modules/ffmpeg/ffmpeg.h>\r
@@ -229,52 +230,52 @@ bool ChannelGridCommand::DoExecute()
 {\r
        BOOST_THROW_EXCEPTION(not_implemented());\r
 \r
-       int index = 1;\r
-       auto self = GetChannels().back();\r
-       \r
-       std::vector<std::wstring> params;\r
-       params.push_back(L"SCREEN");\r
-       params.push_back(L"NAME");\r
-       params.push_back(L"Channel Grid Window");\r
-       auto screen = create_consumer(params);\r
-\r
-       self->output().add(screen);\r
-\r
-       BOOST_FOREACH(auto channel, GetChannels())\r
-       {\r
-               if(channel != self)\r
-               {\r
-                       auto producer = reroute::create_producer(self->frame_factory(), *channel);              \r
-                       self->stage().load(index, producer, false);\r
-                       self->stage().play(index);\r
-                       index++;\r
-               }\r
-       }\r
-\r
-       int n = GetChannels().size()-1;\r
-       double delta = 1.0/static_cast<double>(n);\r
-       for(int x = 0; x < n; ++x)\r
-       {\r
-               for(int y = 0; y < n; ++y)\r
-               {\r
-                       int index = x+y*n+1;\r
-                       auto transform = [=](frame_transform transform) -> frame_transform\r
-                       {               \r
-                               transform.image_transform.fill_translation[0]   = x*delta;\r
-                               transform.image_transform.fill_translation[1]   = y*delta;\r
-                               transform.image_transform.fill_scale[0]                 = delta;\r
-                               transform.image_transform.fill_scale[1]                 = delta;\r
-                               transform.image_transform.clip_translation[0]   = x*delta;\r
-                               transform.image_transform.clip_translation[1]   = y*delta;\r
-                               transform.image_transform.clip_scale[0]                 = delta;\r
-                               transform.image_transform.clip_scale[1]                 = delta;                        \r
-                               return transform;\r
-                       };\r
-                       self->stage().apply_transform(index, transform);\r
-               }\r
-       }\r
-\r
-       return true;\r
+       //int index = 1;\r
+       //auto self = GetChannels().back();\r
+       //\r
+       //std::vector<std::wstring> params;\r
+       //params.push_back(L"SCREEN");\r
+       //params.push_back(L"NAME");\r
+       //params.push_back(L"Channel Grid Window");\r
+       //auto screen = create_consumer(params);\r
+\r
+       //self->output().add(screen);\r
+\r
+       //BOOST_FOREACH(auto channel, GetChannels())\r
+       //{\r
+       //      if(channel != self)\r
+       //      {\r
+       //              auto producer = reroute::create_producer(self->frame_factory(), *channel);              \r
+       //              self->stage().load(index, producer, false);\r
+       //              self->stage().play(index);\r
+       //              index++;\r
+       //      }\r
+       //}\r
+\r
+       //int n = GetChannels().size()-1;\r
+       //double delta = 1.0/static_cast<double>(n);\r
+       //for(int x = 0; x < n; ++x)\r
+       //{\r
+       //      for(int y = 0; y < n; ++y)\r
+       //      {\r
+       //              int index = x+y*n+1;\r
+       //              auto transform = [=](frame_transform transform) -> frame_transform\r
+       //              {               \r
+       //                      transform.image_transform.fill_translation[0]   = x*delta;\r
+       //                      transform.image_transform.fill_translation[1]   = y*delta;\r
+       //                      transform.image_transform.fill_scale[0]                 = delta;\r
+       //                      transform.image_transform.fill_scale[1]                 = delta;\r
+       //                      transform.image_transform.clip_translation[0]   = x*delta;\r
+       //                      transform.image_transform.clip_translation[1]   = y*delta;\r
+       //                      transform.image_transform.clip_scale[0]                 = delta;\r
+       //                      transform.image_transform.clip_scale[1]                 = delta;                        \r
+       //                      return transform;\r
+       //              };\r
+       //              self->stage().apply_transform(index, transform);\r
+       //      }\r
+       //}\r
+\r
+       //return true;\r
 }\r
 \r
 bool CallCommand::DoExecute()\r
@@ -733,19 +734,31 @@ bool LoadbgCommand::DoExecute()
        //Perform loading of the clip\r
        try\r
        {\r
-               _parameters[0] = _parameters[0];\r
-               auto pFP = create_producer(GetChannel()->frame_factory(), GetChannel()->video_format_desc(), _parameters);\r
+               std::shared_ptr<core::frame_producer> pFP;\r
+               \r
+               static boost::wregex expr(L"\\[(?<CHANNEL>\\d+)\\]", boost::regex::icase);\r
+                       \r
+               boost::wsmatch what;\r
+               if(boost::regex_match(_parameters.at(0), what, expr))\r
+               {\r
+                       auto channel_index = boost::lexical_cast<int>(what["CHANNEL"].str());\r
+                       pFP = reroute::create_producer(*GetChannels().at(channel_index-1)); \r
+               }\r
+               else\r
+                       pFP = create_producer(GetChannel()->frame_factory(), GetChannel()->video_format_desc(), _parameters);\r
+               \r
                if(pFP == frame_producer::empty())\r
                        BOOST_THROW_EXCEPTION(file_not_found() << msg_info(_parameters.size() > 0 ? _parameters[0] : L""));\r
 \r
                bool auto_play = std::find(_parameters.begin(), _parameters.end(), L"AUTO") != _parameters.end();\r
 \r
-               auto pFP2 = create_transition_producer(GetChannel()->video_format_desc().field_mode, pFP, transitionInfo);\r
+               auto pFP2 = create_transition_producer(GetChannel()->video_format_desc().field_mode, spl::make_shared_ptr(pFP), transitionInfo);\r
                if(auto_play)\r
                        GetChannel()->stage().load(GetLayerIndex(), pFP2, false, transitionInfo.duration); // TODO: LOOP\r
                else\r
                        GetChannel()->stage().load(GetLayerIndex(), pFP2, false); // TODO: LOOP\r
        \r
+               \r
                SetReplyString(TEXT("202 LOADBG OK\r\n"));\r
 \r
                return true;\r
@@ -791,6 +804,7 @@ bool PlayCommand::DoExecute()
                {\r
                        LoadbgCommand lbg;\r
                        lbg.SetChannel(GetChannel());\r
+                       lbg.SetChannels(GetChannels());\r
                        lbg.SetChannelIndex(GetChannelIndex());\r
                        lbg.SetLayerIntex(GetLayerIndex());\r
                        lbg.SetClientInfo(GetClientInfo());\r
index b3da7020402a3aa50cbff364ed0b17ab0648ac85..caf440e29aa79a40c2c624c65776555f8ea39629 100644 (file)
@@ -251,6 +251,7 @@ AMCPCommandPtr AMCPProtocolStrategy::InterpretCommandString(const std::wstring&
                                }\r
 \r
                                pCommand->SetChannel(pChannel);\r
+                               pCommand->SetChannels(channels_);\r
                                pCommand->SetChannelIndex(channelIndex);\r
                                pCommand->SetLayerIntex(layerIndex);\r
 \r
index 3c4c9c72bdbfd824e4dd81a5619cf0df0f67de1d..b2f9a696fc9c1ad15d592c58cc5b954161859cdc 100644 (file)
@@ -8,23 +8,23 @@
   </paths>\r
   <log-level>trace</log-level>\r
   <accelerator>auto</accelerator>\r
-  <force-deinterlacing>false</force-deinterlacing>\r
   <flash>\r
     <buffer-depth>4</buffer-depth>\r
   </flash>\r
   <channels>\r
     <channel>\r
-      <video-mode>NTSC</video-mode>\r
+      <video-mode>720p5000</video-mode>\r
       <consumers>\r
         <screen>\r
           <device>1</device>\r
-          <name>PROGRAM</name>\r
-          <aspect-ratio>default</aspect-ratio>\r
-          <stretch>uniform</stretch>\r
-          <windowed>true</windowed>\r
-          <key-only>false</key-only>\r
-          <auto-deinterlace>true</auto-deinterlace>\r
-          <vsync>true</vsync>\r
+        </screen>\r
+      </consumers>\r
+    </channel>\r
+    <channel>\r
+      <video-mode>720p5000</video-mode>\r
+      <consumers>\r
+        <screen>\r
+          <device>2</device>\r
         </screen>\r
       </consumers>\r
     </channel>\r