From: ronag Date: Tue, 9 Aug 2011 13:17:54 +0000 (+0000) Subject: 2.0. Added image_consumer and PRINT command. X-Git-Tag: 2.0.1~231 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=beea2625dcb4ed6e7b95e716baaa4220ee4e448e;p=casparcg 2.0. Added image_consumer and PRINT command. git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1109 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d --- diff --git a/core/consumer/frame_consumer.h b/core/consumer/frame_consumer.h index e133412d4..bbea02a3f 100644 --- a/core/consumer/frame_consumer.h +++ b/core/consumer/frame_consumer.h @@ -40,8 +40,7 @@ struct frame_consumer : boost::noncopyable { virtual ~frame_consumer() {} - virtual void send(const safe_ptr& frame) = 0; - virtual size_t buffer_depth() const {return 1;} + virtual bool send(const safe_ptr& frame) = 0; virtual bool key_only() const{ return false;} virtual void initialize(const video_format_desc& format_desc) = 0; virtual std::wstring print() const = 0; @@ -53,8 +52,7 @@ struct frame_consumer : boost::noncopyable struct empty_frame_consumer : public frame_consumer { core::video_format_desc format_desc; - virtual void send(const safe_ptr&){} - virtual size_t buffer_depth() const{return 0;} + virtual bool send(const safe_ptr&){return false;} virtual void initialize(const video_format_desc&){} virtual std::wstring print() const {return L"empty";} virtual bool has_synchronization_clock() const {return false;} diff --git a/core/consumer/output.cpp b/core/consumer/output.cpp index 48b8ea2e0..4a2941c57 100644 --- a/core/consumer/output.cpp +++ b/core/consumer/output.cpp @@ -135,9 +135,12 @@ public: auto frame = consumer->key_only() ? key : fill; if(frame->image_size() == consumer->get_video_format_desc().size) - consumer->send(frame); - - ++it; + { + if(!consumer->send(frame)) + consumers_.erase(it++); + else + ++it; + } } catch(...) { diff --git a/core/core.vcxproj b/core/core.vcxproj index 030bb22e2..c0eb616c8 100644 --- a/core/core.vcxproj +++ b/core/core.vcxproj @@ -72,10 +72,10 @@ $(ProjectDir)tmp\$(Configuration)\ $(ProjectDir)tmp\$(Configuration)\ $(ProjectDir)tmp\$(Configuration)\ - ..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;$(IncludePath) - ..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;$(IncludePath) - ..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;$(IncludePath) - ..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;$(IncludePath) + ..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath) + ..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath) + ..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath) + ..\;..\dependencies\boost_1_44_0\;..\dependencies\tbb\include\;..\dependencies\SFML-1.6\include;..\dependencies\glew-1.6.0\include;..\dependencies\FreeImage\Dist;$(IncludePath) ..\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) ..\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) ..\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) diff --git a/modules/bluefish/consumer/bluefish_consumer.cpp b/modules/bluefish/consumer/bluefish_consumer.cpp index 64307aa47..856aef4c5 100644 --- a/modules/bluefish/consumer/bluefish_consumer.cpp +++ b/modules/bluefish/consumer/bluefish_consumer.cpp @@ -323,9 +323,10 @@ public: consumer_.reset(new bluefish_consumer(format_desc, device_index_, embedded_audio_)); } - virtual void send(const safe_ptr& frame) + virtual bool send(const safe_ptr& frame) { consumer_->send(frame); + return true; } virtual const core::video_format_desc& get_video_format_desc() const diff --git a/modules/decklink/consumer/decklink_consumer.cpp b/modules/decklink/consumer/decklink_consumer.cpp index 78bf816c6..71da7b33f 100644 --- a/modules/decklink/consumer/decklink_consumer.cpp +++ b/modules/decklink/consumer/decklink_consumer.cpp @@ -391,9 +391,10 @@ public: context_.reset([&]{return new decklink_consumer(config_, format_desc);}); } - virtual void send(const safe_ptr& frame) + virtual bool send(const safe_ptr& frame) { context_->send(frame); + return true; } virtual std::wstring print() const @@ -410,11 +411,6 @@ public: { return context_->get_video_format_desc(); } - - virtual size_t buffer_depth() const - { - return context_->buffer_size_; - } }; safe_ptr create_decklink_consumer(const std::vector& params) diff --git a/modules/image/consumer/image_consumer.cpp b/modules/image/consumer/image_consumer.cpp new file mode 100644 index 000000000..75b2f3e5d --- /dev/null +++ b/modules/image/consumer/image_consumer.cpp @@ -0,0 +1,107 @@ +/* +* copyright (c) 2010 Sveriges Television AB +* +* This file is part of CasparCG. +* +* CasparCG is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* CasparCG is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with CasparCG. If not, see . +* +*/ + +#include "image_consumer.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +namespace caspar { + +struct image_consumer : public core::frame_consumer +{ + core::video_format_desc format_desc_; + size_t counter_; +public: + image_consumer() : counter_(0) + { + } + + virtual void initialize(const core::video_format_desc& format_desc) + { + format_desc_ = format_desc; + } + + virtual bool send(const safe_ptr& frame) + { + if(counter_ < core::consumer_buffer_depth()) + ++counter_; + else if(counter_ == core::consumer_buffer_depth()) + { + boost::thread async([=] + { + try + { + auto filename = narrow(env::data_folder()) + boost::posix_time::to_iso_string(boost::posix_time::second_clock::local_time()) + ".png"; + + auto bitmap = std::shared_ptr(FreeImage_Allocate(format_desc_.width, format_desc_.height, 32), FreeImage_Unload); + memcpy(FreeImage_GetBits(bitmap.get()), frame->image_data().begin(), frame->image_size()); + FreeImage_FlipVertical(bitmap.get()); + FreeImage_Save(FIF_PNG, bitmap.get(), filename.c_str(), 0); + } + catch(...) + { + CASPAR_LOG_CURRENT_EXCEPTION(); + } + }); + async.detach(); + + return false; + } + + return true; + } + + virtual size_t buffer_depth() const{return 3;} + + virtual std::wstring print() const + { + return L"image[]"; + } + + virtual const core::video_format_desc& get_video_format_desc() const + { + return format_desc_; + } +}; + +safe_ptr create_image_consumer(const std::vector& params) +{ + if(params.size() < 1 || params[0] != L"IMAGE") + return core::frame_consumer::empty(); + + return make_safe(); +} + + +} diff --git a/modules/image/consumer/image_consumer.h b/modules/image/consumer/image_consumer.h new file mode 100644 index 000000000..2c5bf92f2 --- /dev/null +++ b/modules/image/consumer/image_consumer.h @@ -0,0 +1,39 @@ +/* +* copyright (c) 2010 Sveriges Television AB +* +* This file is part of CasparCG. +* +* CasparCG is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* CasparCG is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with CasparCG. If not, see . +* +*/ +#pragma once + +#include + +#include + +#include + +#include +#include + +namespace caspar { + +namespace core { + struct frame_consumer; +} + +safe_ptr create_image_consumer(const std::vector& params); + +} \ No newline at end of file diff --git a/modules/image/image.cpp b/modules/image/image.cpp index e010fd288..4ede95b6d 100644 --- a/modules/image/image.cpp +++ b/modules/image/image.cpp @@ -21,8 +21,10 @@ #include "producer/image_producer.h" #include "producer/image_scroll_producer.h" +#include "consumer/image_consumer.h" #include +#include #include @@ -34,6 +36,7 @@ void init_image() { core::register_producer_factory(create_image_scroll_producer); core::register_producer_factory(create_image_producer); + core::register_consumer_factory([](const std::vector& params){return create_image_consumer(params);}); } std::wstring get_image_version() diff --git a/modules/image/image.vcxproj b/modules/image/image.vcxproj index 4c12131f8..a159f14cf 100644 --- a/modules/image/image.vcxproj +++ b/modules/image/image.vcxproj @@ -227,6 +227,7 @@ + NotUsing @@ -238,6 +239,7 @@ + diff --git a/modules/image/image.vcxproj.filters b/modules/image/image.vcxproj.filters index 9f76fb774..d5c880138 100644 --- a/modules/image/image.vcxproj.filters +++ b/modules/image/image.vcxproj.filters @@ -10,6 +10,9 @@ {6abd09ae-2ad7-41fa-bfa5-f4614a07be8c} + + {15311b81-1e0d-4114-9bf8-b8f74b292a0f} + @@ -24,6 +27,9 @@ source\producer + + source\consumer + @@ -38,5 +44,8 @@ source\producer + + source\consumer + \ No newline at end of file diff --git a/modules/image/util/image_loader.cpp b/modules/image/util/image_loader.cpp index 30f89831b..a4b51962f 100644 --- a/modules/image/util/image_loader.cpp +++ b/modules/image/util/image_loader.cpp @@ -33,12 +33,6 @@ namespace caspar { std::shared_ptr load_image(const std::string& filename) { - struct FreeImage_initializer - { - FreeImage_initializer(){FreeImage_Initialise(true);} - ~FreeImage_initializer(){FreeImage_DeInitialise();} - } static init; - if(!boost::filesystem::exists(filename)) BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(filename)); diff --git a/modules/oal/consumer/oal_consumer.cpp b/modules/oal/consumer/oal_consumer.cpp index 6341273ad..ff87f4db6 100644 --- a/modules/oal/consumer/oal_consumer.cpp +++ b/modules/oal/consumer/oal_consumer.cpp @@ -79,7 +79,7 @@ public: CASPAR_LOG(info) << print() << " Sucessfully initialized."; } - virtual void send(const safe_ptr& frame) + virtual bool send(const safe_ptr& frame) { if(preroll_count_ < input_.capacity()) { @@ -88,10 +88,10 @@ public: } input_.push(std::vector(frame->audio_data().begin(), frame->audio_data().end())); - } - - virtual size_t buffer_depth() const{return 3;} + return true; + } + virtual bool OnGetData(sf::SoundStream::Chunk& data) { std::vector audio_data; diff --git a/modules/ogl/consumer/ogl_consumer.cpp b/modules/ogl/consumer/ogl_consumer.cpp index e8d04cdec..6a6290507 100644 --- a/modules/ogl/consumer/ogl_consumer.cpp +++ b/modules/ogl/consumer/ogl_consumer.cpp @@ -330,9 +330,10 @@ public: consumer_.reset(new ogl_consumer(screen_index_, stretch_, windowed_, format_desc)); } - virtual void send(const safe_ptr& frame) + virtual bool send(const safe_ptr& frame) { consumer_->send(frame); + return true; } virtual std::wstring print() const diff --git a/protocol/amcp/AMCPCommandsImpl.cpp b/protocol/amcp/AMCPCommandsImpl.cpp index 689d6f3f7..dd5bc5669 100644 --- a/protocol/amcp/AMCPCommandsImpl.cpp +++ b/protocol/amcp/AMCPCommandsImpl.cpp @@ -787,6 +787,15 @@ bool ClearCommand::DoExecute() return true; } +bool PrintCommand::DoExecute() +{ + GetChannel()->output()->add(99978, create_consumer(boost::assign::list_of(L"IMAGE"))); + + SetReplyString(TEXT("202 PRINT OK\r\n")); + + return true; +} + bool CGCommand::DoExecute() { std::wstring command = _parameters[0]; diff --git a/protocol/amcp/AMCPCommandsImpl.h b/protocol/amcp/AMCPCommandsImpl.h index 341c6a63e..0ba71f57b 100644 --- a/protocol/amcp/AMCPCommandsImpl.h +++ b/protocol/amcp/AMCPCommandsImpl.h @@ -96,6 +96,13 @@ class ClearCommand : public AMCPCommandBase bool DoExecute(); }; +class PrintCommand : public AMCPCommandBase +{ + std::wstring print() const { return L"PrintCommand";} + bool DoExecute(); +}; + + class CGCommand : public AMCPCommandBase { std::wstring print() const { return L"CGCommand";} diff --git a/protocol/amcp/AMCPProtocolStrategy.cpp b/protocol/amcp/AMCPProtocolStrategy.cpp index 65edbd5da..4ad90ea2d 100644 --- a/protocol/amcp/AMCPProtocolStrategy.cpp +++ b/protocol/amcp/AMCPProtocolStrategy.cpp @@ -321,6 +321,7 @@ AMCPCommandPtr AMCPProtocolStrategy::CommandFactory(const std::wstring& str) else if(s == TEXT("PLAY")) return std::make_shared(); else if(s == TEXT("STOP")) return std::make_shared(); else if(s == TEXT("CLEAR")) return std::make_shared(); + else if(s == TEXT("PRINT")) return std::make_shared(); else if(s == TEXT("CG")) return std::make_shared(); else if(s == TEXT("DATA")) return std::make_shared(); else if(s == TEXT("CINF")) return std::make_shared();