]> git.sesse.net Git - casparcg/commitdiff
2.0. Added image_consumer and PRINT command.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 9 Aug 2011 13:17:54 +0000 (13:17 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 9 Aug 2011 13:17:54 +0000 (13:17 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1109 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

16 files changed:
core/consumer/frame_consumer.h
core/consumer/output.cpp
core/core.vcxproj
modules/bluefish/consumer/bluefish_consumer.cpp
modules/decklink/consumer/decklink_consumer.cpp
modules/image/consumer/image_consumer.cpp [new file with mode: 0644]
modules/image/consumer/image_consumer.h [new file with mode: 0644]
modules/image/image.cpp
modules/image/image.vcxproj
modules/image/image.vcxproj.filters
modules/image/util/image_loader.cpp
modules/oal/consumer/oal_consumer.cpp
modules/ogl/consumer/ogl_consumer.cpp
protocol/amcp/AMCPCommandsImpl.cpp
protocol/amcp/AMCPCommandsImpl.h
protocol/amcp/AMCPProtocolStrategy.cpp

index e133412d4ba2182070e1c30e1bf354341e86c9ed..bbea02a3f52cd58a06f06509bbc76f6b0a407bf0 100644 (file)
@@ -40,8 +40,7 @@ struct frame_consumer : boost::noncopyable
 {\r
        virtual ~frame_consumer() {}\r
        \r
-       virtual void send(const safe_ptr<read_frame>& frame) = 0;\r
-       virtual size_t buffer_depth() const {return 1;}\r
+       virtual bool send(const safe_ptr<read_frame>& frame) = 0;\r
        virtual bool key_only() const{ return false;}\r
        virtual void initialize(const video_format_desc& format_desc) = 0;\r
        virtual std::wstring print() const = 0;\r
@@ -53,8 +52,7 @@ struct frame_consumer : boost::noncopyable
                struct empty_frame_consumer : public frame_consumer\r
                {\r
                        core::video_format_desc format_desc;\r
-                       virtual void send(const safe_ptr<read_frame>&){}\r
-                       virtual size_t buffer_depth() const{return 0;}\r
+                       virtual bool send(const safe_ptr<read_frame>&){return false;}\r
                        virtual void initialize(const video_format_desc&){}\r
                        virtual std::wstring print() const {return L"empty";}\r
                        virtual bool has_synchronization_clock() const {return false;}\r
index 48b8ea2e0606bc7274141dba8bb21331f35b6921..4a2941c575d287f262bbca26c7df1bb8d55e94f1 100644 (file)
@@ -135,9 +135,12 @@ public:
                                        auto frame = consumer->key_only() ? key : fill;\r
 \r
                                        if(frame->image_size() == consumer->get_video_format_desc().size)\r
-                                               consumer->send(frame);\r
-\r
-                                       ++it;\r
+                                       {       \r
+                                               if(!consumer->send(frame))\r
+                                                       consumers_.erase(it++);\r
+                                               else\r
+                                                       ++it;\r
+                                       }\r
                                }\r
                                catch(...)\r
                                {\r
index 030bb22e2431bb118858ad018341077e37d7a538..c0eb616c8e547ea93b07c0e4b42817676464386e 100644 (file)
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">$(ProjectDir)tmp\$(Configuration)\</IntDir>\r
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;$(IncludePath)</IncludePath>\r
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;$(IncludePath)</IncludePath>\r
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;$(IncludePath)</IncludePath>\r
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath)</IncludePath>\r
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath)</IncludePath>\r
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\dependencies\BluefishSDK_V5_8_0_31\Lib\;..\dependencies\boost_1_44_0\stage\lib\;..\dependencies\ffmpeg 0.6\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\dependencies\BluefishSDK_V5_8_0_31\Lib\;..\dependencies\boost_1_44_0\stage\lib\;..\dependencies\ffmpeg 0.6\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\dependencies\BluefishSDK_V5_8_0_31\Lib\;..\dependencies\boost_1_44_0\stage\lib\;..\dependencies\ffmpeg 0.6\lib\;..\dependencies\FreeImage\Dist\;..\dependencies\glew-1.6.0\lib;..\dependencies\SFML-1.6\lib\;..\dependencies\tbb\lib\ia32\vc10\;$(LibraryPath)</LibraryPath>\r
index 64307aa47bac7386a41f2070468fb5e0756c68ed..856aef4c553166bcff994aa6c5ea1066c0314e0f 100644 (file)
@@ -323,9 +323,10 @@ public:
                consumer_.reset(new bluefish_consumer(format_desc, device_index_, embedded_audio_));\r
        }\r
        \r
-       virtual void send(const safe_ptr<core::read_frame>& frame)\r
+       virtual bool send(const safe_ptr<core::read_frame>& frame)\r
        {\r
                consumer_->send(frame);\r
+               return true;\r
        }\r
 \r
        virtual const core::video_format_desc& get_video_format_desc() const\r
index 78bf816c6cf05b3ad88af55b9d6173111d4d2a5e..71da7b33fadace2748709f66d8ef465ca2f07208 100644 (file)
@@ -391,9 +391,10 @@ public:
                context_.reset([&]{return new decklink_consumer(config_, format_desc);});\r
        }\r
        \r
-       virtual void send(const safe_ptr<core::read_frame>& frame)\r
+       virtual bool send(const safe_ptr<core::read_frame>& frame)\r
        {\r
                context_->send(frame);\r
+               return true;\r
        }\r
        \r
        virtual std::wstring print() const\r
@@ -410,11 +411,6 @@ public:
        {\r
                return context_->get_video_format_desc();\r
        }\r
-\r
-       virtual size_t buffer_depth() const\r
-       {\r
-               return context_->buffer_size_;\r
-       }\r
 };     \r
 \r
 safe_ptr<core::frame_consumer> create_decklink_consumer(const std::vector<std::wstring>& params) \r
diff --git a/modules/image/consumer/image_consumer.cpp b/modules/image/consumer/image_consumer.cpp
new file mode 100644 (file)
index 0000000..75b2f3e
--- /dev/null
@@ -0,0 +1,107 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\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
+*/\r
\r
+#include "image_consumer.h"\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/env.h>\r
+#include <common/log/log.h>\r
+#include <common/utility/string.h>\r
+\r
+#include <core/consumer/frame_consumer.h>\r
+#include <core/video_format.h>\r
+#include <core/mixer/read_frame.h>\r
+\r
+#include <boost/date_time/posix_time/posix_time.hpp>\r
+#include <boost/thread.hpp>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <FreeImage.h>\r
+\r
+namespace caspar {\r
+       \r
+struct image_consumer : public core::frame_consumer\r
+{\r
+       core::video_format_desc format_desc_;\r
+       size_t counter_;\r
+public:\r
+       image_consumer() : counter_(0)\r
+       {\r
+       }\r
+\r
+       virtual void initialize(const core::video_format_desc& format_desc)\r
+       {\r
+               format_desc_ = format_desc;\r
+       }\r
+       \r
+       virtual bool send(const safe_ptr<core::read_frame>& frame)\r
+       {                               \r
+               if(counter_ < core::consumer_buffer_depth())\r
+                       ++counter_;\r
+               else if(counter_ == core::consumer_buffer_depth())\r
+               {\r
+                       boost::thread async([=]\r
+                       {\r
+                               try\r
+                               {\r
+                                       auto filename = narrow(env::data_folder()) +  boost::posix_time::to_iso_string(boost::posix_time::second_clock::local_time()) + ".png";\r
+\r
+                                       auto bitmap = std::shared_ptr<FIBITMAP>(FreeImage_Allocate(format_desc_.width, format_desc_.height, 32), FreeImage_Unload);\r
+                                       memcpy(FreeImage_GetBits(bitmap.get()), frame->image_data().begin(), frame->image_size());\r
+                                       FreeImage_FlipVertical(bitmap.get());\r
+                                       FreeImage_Save(FIF_PNG, bitmap.get(), filename.c_str(), 0);\r
+                               }\r
+                               catch(...)\r
+                               {\r
+                                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               }\r
+                       });\r
+                       async.detach();\r
+\r
+                       return false;\r
+               }\r
+\r
+               return true;\r
+       }\r
+\r
+       virtual size_t buffer_depth() const{return 3;}\r
+\r
+       virtual std::wstring print() const\r
+       {\r
+               return L"image[]";\r
+       }\r
+\r
+       virtual const core::video_format_desc& get_video_format_desc() const\r
+       {\r
+               return format_desc_;\r
+       }\r
+};\r
+\r
+safe_ptr<core::frame_consumer> create_image_consumer(const std::vector<std::wstring>& params)\r
+{\r
+       if(params.size() < 1 || params[0] != L"IMAGE")\r
+               return core::frame_consumer::empty();\r
+\r
+       return make_safe<image_consumer>();\r
+}\r
+\r
+\r
+}\r
diff --git a/modules/image/consumer/image_consumer.h b/modules/image/consumer/image_consumer.h
new file mode 100644 (file)
index 0000000..2c5bf92
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\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
+*/\r
+#pragma once\r
+\r
+#include <common/memory/safe_ptr.h>\r
+\r
+#include <core/video_format.h>\r
+\r
+#include <boost/property_tree/ptree.hpp>\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace caspar { \r
+\r
+namespace core {\r
+       struct frame_consumer;\r
+}\r
+       \r
+safe_ptr<core::frame_consumer> create_image_consumer(const std::vector<std::wstring>& params);\r
+\r
+}
\ No newline at end of file
index e010fd28807414808c95a328d2689b5a57cf2db6..4ede95b6d3dd3585ec87bcb47d729e0e6511939a 100644 (file)
 \r
 #include "producer/image_producer.h"\r
 #include "producer/image_scroll_producer.h"\r
+#include "consumer/image_consumer.h"\r
 \r
 #include <core/producer/frame_producer.h>\r
+#include <core/consumer/frame_consumer.h>\r
 \r
 #include <common/utility/string.h>\r
 \r
@@ -34,6 +36,7 @@ void init_image()
 {\r
        core::register_producer_factory(create_image_scroll_producer);\r
        core::register_producer_factory(create_image_producer);\r
+       core::register_consumer_factory([](const std::vector<std::wstring>& params){return create_image_consumer(params);});\r
 }\r
 \r
 std::wstring get_image_version()\r
index 4c12131f8b717ea7eed63a251741ab75bb1a148b..a159f14cf1eb895a9c05226fe814d06e20dce273 100644 (file)
     </ProjectReference>\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <ClCompile Include="consumer\image_consumer.cpp" />\r
     <ClCompile Include="image.cpp" />\r
     <ClCompile Include="producer\image_producer.cpp">\r
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">NotUsing</PrecompiledHeader>\r
     <ClCompile Include="util\image_loader.cpp" />\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <ClInclude Include="consumer\image_consumer.h" />\r
     <ClInclude Include="image.h" />\r
     <ClInclude Include="producer\image_producer.h" />\r
     <ClInclude Include="producer\image_scroll_producer.h" />\r
index 9f76fb774f2d543a2c7c9841d68dcafb5bd98f31..d5c88013878359bf09ebcb9144217e393c300a5c 100644 (file)
@@ -10,6 +10,9 @@
     <Filter Include="source\util">\r
       <UniqueIdentifier>{6abd09ae-2ad7-41fa-bfa5-f4614a07be8c}</UniqueIdentifier>\r
     </Filter>\r
+    <Filter Include="source\consumer">\r
+      <UniqueIdentifier>{15311b81-1e0d-4114-9bf8-b8f74b292a0f}</UniqueIdentifier>\r
+    </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="producer\image_producer.cpp">\r
@@ -24,6 +27,9 @@
     <ClCompile Include="producer\image_scroll_producer.cpp">\r
       <Filter>source\producer</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="consumer\image_consumer.cpp">\r
+      <Filter>source\consumer</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="producer\image_producer.h">\r
@@ -38,5 +44,8 @@
     <ClInclude Include="producer\image_scroll_producer.h">\r
       <Filter>source\producer</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="consumer\image_consumer.h">\r
+      <Filter>source\consumer</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index 30f89831bd443aac03a94314d9e404923e9f3a56..a4b51962f11739a8bde8b594a3de6942b64bcdf1 100644 (file)
@@ -33,12 +33,6 @@ namespace caspar {
 \r
 std::shared_ptr<FIBITMAP> load_image(const std::string& filename)\r
 {\r
-       struct FreeImage_initializer\r
-       {\r
-               FreeImage_initializer(){FreeImage_Initialise(true);}\r
-               ~FreeImage_initializer(){FreeImage_DeInitialise();}\r
-       } static init;\r
-\r
        if(!boost::filesystem::exists(filename))\r
                BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(filename));\r
 \r
index 6341273ad375cebc06f5e76f0ea84371c5794080..ff87f4db6076452d179c564da7b66ec66e6c33f6 100644 (file)
@@ -79,7 +79,7 @@ public:
                CASPAR_LOG(info) << print() << " Sucessfully initialized.";\r
        }\r
        \r
-       virtual void send(const safe_ptr<core::read_frame>& frame)\r
+       virtual bool send(const safe_ptr<core::read_frame>& frame)\r
        {                       \r
                if(preroll_count_ < input_.capacity())\r
                {\r
@@ -88,10 +88,10 @@ public:
                }\r
 \r
                input_.push(std::vector<int16_t>(frame->audio_data().begin(), frame->audio_data().end()));      \r
-       }\r
-\r
-       virtual size_t buffer_depth() const{return 3;}\r
 \r
+               return true;\r
+       }\r
+       \r
        virtual bool OnGetData(sf::SoundStream::Chunk& data)\r
        {               \r
                std::vector<short> audio_data;          \r
index e8d04cdec0c3d353bd9156cd1abf3f96ea422a9a..6a62905075e757466a3ae90341f7eee9063585f3 100644 (file)
@@ -330,9 +330,10 @@ public:
                consumer_.reset(new ogl_consumer(screen_index_, stretch_, windowed_, format_desc));\r
        }\r
        \r
-       virtual void send(const safe_ptr<core::read_frame>& frame)\r
+       virtual bool send(const safe_ptr<core::read_frame>& frame)\r
        {\r
                consumer_->send(frame);\r
+               return true;\r
        }\r
        \r
        virtual std::wstring print() const\r
index 689d6f3f7824694fc5981c269e5fbb0b9130b747..dd5bc56698c76f05e5b67cbe0b54ff094ba8521e 100644 (file)
@@ -787,6 +787,15 @@ bool ClearCommand::DoExecute()
        return true;\r
 }\r
 \r
+bool PrintCommand::DoExecute()\r
+{\r
+       GetChannel()->output()->add(99978, create_consumer(boost::assign::list_of(L"IMAGE")));\r
+               \r
+       SetReplyString(TEXT("202 PRINT OK\r\n"));\r
+\r
+       return true;\r
+}\r
+\r
 bool CGCommand::DoExecute()\r
 {\r
        std::wstring command = _parameters[0];\r
index 341c6a63ee5a0c48c0ae2aed8ce78c061d5b99b2..0ba71f57b9094781b09142b85f0d623a8feb5a12 100644 (file)
@@ -96,6 +96,13 @@ class ClearCommand : public AMCPCommandBase<true, AddToQueue, 0>
        bool DoExecute();\r
 };\r
 \r
+class PrintCommand : public AMCPCommandBase<true, AddToQueue, 0>\r
+{\r
+       std::wstring print() const { return L"PrintCommand";}\r
+       bool DoExecute();\r
+};\r
+\r
+\r
 class CGCommand : public AMCPCommandBase<true, AddToQueue, 1>\r
 {\r
        std::wstring print() const { return L"CGCommand";}\r
index 65edbd5da7b9ab06cd3e9e9a764027fdc99b70e9..4ad90ea2d0e533a552cbeefd77d342f6baabee35 100644 (file)
@@ -321,6 +321,7 @@ AMCPCommandPtr AMCPProtocolStrategy::CommandFactory(const std::wstring& str)
        else if(s == TEXT("PLAY"))              return std::make_shared<PlayCommand>();\r
        else if(s == TEXT("STOP"))              return std::make_shared<StopCommand>();\r
        else if(s == TEXT("CLEAR"))             return std::make_shared<ClearCommand>();\r
+       else if(s == TEXT("PRINT"))             return std::make_shared<PrintCommand>();\r
        else if(s == TEXT("CG"))                return std::make_shared<CGCommand>();\r
        else if(s == TEXT("DATA"))              return std::make_shared<DataCommand>();\r
        else if(s == TEXT("CINF"))              return std::make_shared<CinfCommand>();\r