]> git.sesse.net Git - casparcg/commitdiff
- ogl_consumer: Fixed params for create.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 21 Dec 2011 15:41:16 +0000 (15:41 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 21 Dec 2011 15:41:16 +0000 (15:41 +0000)
- Added channel-grid functionality.

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

13 files changed:
core/consumer/output.cpp
core/consumer/output.h
core/producer/channel/channel_producer.cpp [new file with mode: 0644]
core/producer/channel/channel_producer.h [new file with mode: 0644]
core/video_channel.cpp
core/video_channel.h
core/video_format.cpp
modules/ogl/consumer/ogl_consumer.cpp
protocol/amcp/AMCPCommandsImpl.cpp
protocol/amcp/AMCPCommandsImpl.h
protocol/amcp/AMCPProtocolStrategy.cpp
shell/casparcg.config
shell/server.cpp

index 8476e676dcdf9306f66a5b8ed073a7872c53165a..4133b0d6e5140a61629c472c57b5caa4a2d2dd16 100644 (file)
@@ -254,6 +254,14 @@ public:
                        return info;\r
                }, high_priority));\r
        }\r
+\r
+       bool empty()\r
+       {\r
+               return executor_.invoke([this]\r
+               {\r
+                       return consumers_.empty();\r
+               });\r
+       }\r
 };\r
 \r
 output::output(const safe_ptr<diagnostics::graph>& graph, const video_format_desc& format_desc, int channel_index) : impl_(new implementation(graph, format_desc, channel_index)){}\r
@@ -264,4 +272,5 @@ void output::remove(const safe_ptr<frame_consumer>& consumer){impl_->remove(cons
 void output::send(const std::pair<safe_ptr<read_frame>, std::shared_ptr<void>>& frame) {impl_->send(frame); }\r
 void output::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
 boost::unique_future<boost::property_tree::wptree> output::info() const{return impl_->info();}\r
+bool output::empty() const{return impl_->empty();}\r
 }}
\ No newline at end of file
index 02477b5022c2cca74afbe9177a7065c5910ed702..1336a6694a5605c69b652b1f683de1ab2b6cbc73 100644 (file)
@@ -53,6 +53,8 @@ public:
        void set_video_format_desc(const video_format_desc& format_desc);\r
 \r
        boost::unique_future<boost::property_tree::wptree> info() const;\r
+\r
+       bool empty() const;\r
 private:\r
        struct implementation;\r
        safe_ptr<implementation> impl_;\r
diff --git a/core/producer/channel/channel_producer.cpp b/core/producer/channel/channel_producer.cpp
new file mode 100644 (file)
index 0000000..392ddb3
--- /dev/null
@@ -0,0 +1,216 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../../stdafx.h"\r
+\r
+#include "channel_producer.h"\r
+\r
+#include "../../consumer/frame_consumer.h"\r
+#include "../../consumer/output.h"\r
+#include "../../video_channel.h"\r
+\r
+#include "../frame/basic_frame.h"\r
+#include "../frame/frame_factory.h"\r
+#include "../../mixer/write_frame.h"\r
+#include "../../mixer/read_frame.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+\r
+namespace caspar { namespace core {\r
+\r
+class channel_consumer : public frame_consumer\r
+{      \r
+       tbb::concurrent_bounded_queue<std::shared_ptr<read_frame>> frame_buffer_;\r
+       core::video_format_desc format_desc_;\r
+       int                                             channel_index_;\r
+       tbb::atomic<bool>               is_running_;\r
+\r
+public:\r
+       channel_consumer() \r
+       {\r
+               is_running_ = true;\r
+               frame_buffer_.set_capacity(2);\r
+       }\r
+\r
+       ~channel_consumer()\r
+       {\r
+               stop();\r
+       }\r
+\r
+       // frame_consumer\r
+\r
+       virtual bool send(const safe_ptr<read_frame>& frame) override\r
+       {\r
+               frame_buffer_.try_push(frame);\r
+               return is_running_;\r
+       }\r
+\r
+       virtual void initialize(const core::video_format_desc& format_desc, int channel_index) override\r
+       {\r
+               format_desc_    = format_desc;\r
+               channel_index_ = channel_index;\r
+       }\r
+\r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"[channel-consumer|" + boost::lexical_cast<std::wstring>(channel_index_) + L"]";\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"channel-consumer");\r
+               info.add(L"channel-index", channel_index_);\r
+               return info;\r
+       }\r
+       \r
+       virtual bool has_synchronization_clock() const override\r
+       {\r
+               return false;\r
+       }\r
+\r
+       virtual size_t buffer_depth() const override\r
+       {\r
+               return 1;\r
+       }\r
+\r
+       virtual int index() const override\r
+       {\r
+               return 78500 + channel_index_;\r
+       }\r
+\r
+       // channel_consumer\r
+\r
+       void stop()\r
+       {\r
+               is_running_ = false;\r
+               frame_buffer_.try_push(make_safe<read_frame>());\r
+       }\r
+       \r
+       const core::video_format_desc& get_video_format_desc()\r
+       {\r
+               return format_desc_;\r
+       }\r
+\r
+       std::shared_ptr<read_frame> receive()\r
+       {\r
+               if(!is_running_)\r
+                       return make_safe<read_frame>();\r
+               std::shared_ptr<read_frame> frame;\r
+               frame_buffer_.try_pop(frame);\r
+               return frame;\r
+       }\r
+};\r
+       \r
+class channel_producer : public frame_producer\r
+{\r
+       const safe_ptr<frame_factory>           frame_factory_;\r
+       const safe_ptr<channel_consumer>        consumer_;\r
+\r
+       std::queue<safe_ptr<basic_frame>>       frame_buffer_;\r
+       safe_ptr<basic_frame>                           last_frame_;\r
+\r
+public:\r
+       explicit channel_producer(const safe_ptr<frame_factory>& frame_factory, const safe_ptr<video_channel>& channel) \r
+               : frame_factory_(frame_factory)\r
+               , consumer_(make_safe<channel_consumer>())\r
+               , last_frame_(basic_frame::empty())\r
+       {\r
+               channel->output()->add(consumer_);\r
+               CASPAR_LOG(info) << print() << L" Initialized";\r
+       }\r
+\r
+       ~channel_producer()\r
+       {\r
+               consumer_->stop();\r
+               CASPAR_LOG(info) << print() << L" Uninitialized";\r
+       }\r
+\r
+       // frame_producer\r
+                       \r
+       virtual safe_ptr<basic_frame> receive(int) override\r
+       {\r
+               auto format_desc = consumer_->get_video_format_desc();\r
+\r
+               bool half_speed = std::abs(format_desc.fps / 2.0 - frame_factory_->get_video_format_desc().fps) < 0.01;\r
+               \r
+               if(half_speed && frame_buffer_.size() >= 2)\r
+               {                               \r
+                       frame_buffer_.pop();\r
+                       auto frame = frame_buffer_.front();\r
+                       frame_buffer_.pop();\r
+                       return last_frame_ = frame;\r
+               }\r
+               else if(!frame_buffer_.empty())\r
+               {\r
+                       auto frame = frame_buffer_.front();\r
+                       frame_buffer_.pop();\r
+                       return last_frame_ = frame;\r
+               }\r
+               \r
+               auto read_frame = consumer_->receive();\r
+               if(!read_frame || read_frame->image_data().empty())\r
+                       return basic_frame::late();             \r
+               \r
+               core::pixel_format_desc desc;\r
+               desc.pix_fmt = core::pixel_format::bgra;\r
+               desc.planes.push_back(core::pixel_format_desc::plane(format_desc.width, format_desc.height, 4));\r
+               auto frame = frame_factory_->create_frame(this, desc);\r
+\r
+               memcpy(frame->image_data().begin(), read_frame->image_data().begin(), read_frame->image_data().size());\r
+               frame->commit();\r
+\r
+               frame_buffer_.push(frame);      \r
+               \r
+               bool double_speed = std::abs(frame_factory_->get_video_format_desc().fps / 2.0 - format_desc.fps) < 0.01;\r
+\r
+               if(double_speed)        \r
+                       frame_buffer_.push(frame);\r
+\r
+               return receive(0);\r
+       }       \r
+\r
+       virtual safe_ptr<basic_frame> last_frame() const override\r
+       {\r
+               return last_frame_; \r
+       }       \r
+\r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"channel[]";\r
+       }\r
+\r
+       boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"channel-producer");\r
+               return info;\r
+       }\r
+};\r
+\r
+safe_ptr<frame_producer> create_channel_producer(const safe_ptr<core::frame_factory>& frame_factory, const safe_ptr<video_channel>& channel)\r
+{\r
+       return make_safe<channel_producer>(frame_factory, channel);\r
+}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/producer/channel/channel_producer.h b/core/producer/channel/channel_producer.h
new file mode 100644 (file)
index 0000000..6d39ce6
--- /dev/null
@@ -0,0 +1,36 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#pragma once\r
+\r
+#include "../frame_producer.h"\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { namespace core {\r
+\r
+class video_channel;\r
+struct frame_factory;\r
+\r
+safe_ptr<frame_producer> create_channel_producer(const safe_ptr<core::frame_factory>& frame_factory, const safe_ptr<video_channel>& channel);\r
+\r
+}}\r
index 411a9fe8babfc6a4d19240e432a3ef56240885b1..79340d213ac4ae0e8da1b0621c2f730a33cb91b6 100644 (file)
@@ -41,14 +41,14 @@ namespace caspar { namespace core {
 \r
 struct video_channel::implementation : boost::noncopyable\r
 {\r
-       const int                                               index_;\r
-       video_format_desc                               format_desc_;\r
-       const safe_ptr<ogl_device>              ogl_;\r
-       safe_ptr<diagnostics::graph>    graph_;\r
-\r
-       safe_ptr<caspar::core::output>  output_;\r
-       safe_ptr<caspar::core::mixer>   mixer_;\r
-       safe_ptr<caspar::core::stage>   stage_;\r
+       const int                                                               index_;\r
+       video_format_desc                                               format_desc_;\r
+       const safe_ptr<ogl_device>                              ogl_;\r
+       const safe_ptr<diagnostics::graph>              graph_;\r
+\r
+       const safe_ptr<caspar::core::output>    output_;\r
+       const safe_ptr<caspar::core::mixer>             mixer_;\r
+       const safe_ptr<caspar::core::stage>             stage_;\r
        \r
 public:\r
        implementation(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl)  \r
@@ -121,5 +121,6 @@ safe_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
+int video_channel::index() const {return impl_->index_;}\r
 \r
 }}
\ No newline at end of file
index 51c2267ff2ba992e652cd89f7b2925c6ab36f892..c69bd636e38190d62b605e4f02fc63d357ee1c4d 100644 (file)
@@ -49,6 +49,8 @@ public:
        \r
        boost::property_tree::wptree info() const;\r
 \r
+       int index() const;\r
+\r
 private:\r
        struct implementation;\r
        safe_ptr<implementation> impl_;\r
index 1a15474d661fb83464985c145dc6252f766d032d..833f491b5adb8c0e04b385d0e12049e30f3d6df1 100644 (file)
@@ -52,7 +52,7 @@ const video_format_desc format_descs[video_format::count] =
 {                                                                         \r
        DEFINE_VIDEOFORMATDESC(video_format::pal                ,720,  576,  1024, 576,  field_mode::upper,                     25,             1,               boost::assign::list_of(3840),                                                  L"PAL"), \r
        DEFINE_VIDEOFORMATDESC(video_format::ntsc               ,720,  486,  720,  534,  field_mode::lower,                     30000,  1001,    boost::assign::list_of(3204)(3202)(3204)(3202)(3204),  L"NTSC"), \r
-       DEFINE_VIDEOFORMATDESC(video_format::x576p2500  ,720,  576,  720,  576,  field_mode::progressive,       25,             1,               boost::assign::list_of(3840),                                                  L"576p2500"),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x576p2500  ,1024, 576,  1024, 576,  field_mode::progressive,       25,             1,               boost::assign::list_of(3840),                                                  L"576p2500"),\r
        DEFINE_VIDEOFORMATDESC(video_format::x720p2500  ,1280, 720,  1280, 720,  field_mode::progressive,       25,             1,               boost::assign::list_of(3840),                                                  L"720p2500"), \r
        DEFINE_VIDEOFORMATDESC(video_format::x720p5000  ,1280, 720,  1280, 720,  field_mode::progressive,       50,             1,               boost::assign::list_of(1920),                                                  L"720p5000"), \r
        DEFINE_VIDEOFORMATDESC(video_format::x720p5994  ,1280, 720,  1280, 720,  field_mode::progressive,       60000,  1001,    boost::assign::list_of(1602)(1601)(1602)(1601)(1602),  L"720p5994"),\r
index 2f2dcde7575cb23e5d53c951194db26ce6acb1ab..19224546f46636d9912e1be4b5b028c29ff39c31 100644 (file)
@@ -499,14 +499,17 @@ safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&
        \r
        configuration config;\r
                \r
-       if(params.size() > 1) \r
-               config.screen_index = lexical_cast_or_default<int>(params[2], config.screen_index);\r
-\r
-       if(params.size() > 2) \r
-               config.windowed = lexical_cast_or_default<bool>(params[3], config.windowed);\r
-\r
+       auto device_it = std::find(params.begin(), params.end(), L"DEVICE");\r
+       if(device_it != params.end() && ++device_it != params.end())\r
+               config.screen_index = boost::lexical_cast<int>(*device_it);\r
+               \r
+       config.key_only = std::find(params.begin(), params.end(), L"WINDOWED") != params.end();\r
        config.key_only = std::find(params.begin(), params.end(), L"KEY_ONLY") != params.end();\r
 \r
+       auto name_it    = std::find(params.begin(), params.end(), L"NAME");\r
+       if(name_it != params.end() && ++name_it != params.end())\r
+               config.name = *name_it;\r
+\r
        return make_safe<ogl_consumer_proxy>(config);\r
 }\r
 \r
index 881acf68079dee6b05b9bacc71a641b1f654862c..e4aba41249aadd134f13b62db9672dc3acd5086c 100644 (file)
@@ -54,6 +54,7 @@
 #include <modules/flash/producer/cg_producer.h>\r
 #include <modules/ffmpeg/producer/util/util.h>\r
 #include <modules/image/image.h>\r
+#include <modules/ogl/ogl.h>\r
 \r
 #include <algorithm>\r
 #include <locale>\r
@@ -225,13 +226,23 @@ bool DiagnosticsCommand::DoExecute()
 bool ChannelGridCommand::DoExecute()\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 != GetChannel())\r
+               if(channel != self)\r
                {\r
-                       auto producer = create_channel_producer(GetChannel()->mixer(), channel);                \r
-                       GetChannel()->stage()->load(index, producer, false);\r
-                       GetChannel()->stage()->play(index);\r
+                       auto producer = create_channel_producer(self->mixer(), channel);                \r
+                       self->stage()->load(index, producer, false);\r
+                       self->stage()->play(index);\r
                        index++;\r
                }\r
        }\r
@@ -255,7 +266,7 @@ bool ChannelGridCommand::DoExecute()
                                transform.clip_scale[1]                 = delta;                        \r
                                return transform;\r
                        };\r
-                       GetChannel()->stage()->apply_frame_transform(index, transform);\r
+                       self->stage()->apply_frame_transform(index, transform);\r
                }\r
        }\r
 \r
index a2ccc88b8d2efd1c8844e37fc46eb1737a5bdd79..62e569710a06b68a989e2ae38c9837d0135d3f5c 100644 (file)
@@ -32,7 +32,7 @@ std::wstring ListTemplates();
 \r
 namespace amcp {\r
        \r
-class ChannelGridCommand : public AMCPCommandBase<true, AddToQueue, 0>\r
+class ChannelGridCommand : public AMCPCommandBase<false, AddToQueue, 0>\r
 {\r
        std::wstring print() const { return L"ChannelGridCommand";}\r
        bool DoExecute();\r
index 5ab1388a611d566ec6858a6722828d3958e31e0f..b40ae6f303dff76529c1bc97eb3fd5a81f937a18 100644 (file)
@@ -185,6 +185,7 @@ AMCPCommandPtr AMCPProtocolStrategy::InterpretCommandString(const std::wstring&
                        }\r
                        else\r
                        {\r
+                               pCommand->SetChannels(channels_);\r
                                //Set scheduling\r
                                if(commandSwitch.size() > 0) {\r
                                        transform(commandSwitch.begin(), commandSwitch.end(), commandSwitch.begin(), toupper);\r
@@ -249,7 +250,6 @@ 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 07893501e4de44f2cf832b3661eb67743334f901..99d063c1d64161ead9c871c9de0af36c89752149 100644 (file)
@@ -1,18 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>\r
 <configuration>\r
   <paths>\r
-    <media-path>C:\casparmedia\_media\</media-path>\r
+    <media-path>D:\casparcg\_media\</media-path>\r
     <log-path>D:\casparcg\_log\</log-path>\r
     <data-path>D:\casparcg\_data\</data-path>\r
     <template-path>D:\casparcg\_templates\</template-path>\r
   </paths>\r
   <log-level>trace</log-level>\r
+  <channel-grid>true</channel-grid>\r
   <channels>\r
+    <channel>\r
+      <video-mode>PAL</video-mode>\r
+      <consumers>\r
+        <screen>            \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
         </screen>\r
       </consumers>\r
     </channel>\r
index f1419cc91b1fbe5a8011cd65381918fd987ba6dc..4a3b06f49e23cde3744f211f84a3ad407c638ec2 100644 (file)
@@ -142,6 +142,10 @@ struct server::implementation : boost::noncopyable
                                }\r
                        }                                                       \r
                }\r
+\r
+               // Dummy diagnostics channel\r
+               if(env::properties().get(L"configuration.channel-grid", false))\r
+                       channels_.push_back(make_safe<video_channel>(channels_.size()+1, core::video_format_desc::get(core::video_format::x576p2500), ogl_));\r
        }\r
                \r
        void setup_controllers(const boost::property_tree::wptree& pt)\r