--- /dev/null
+#include "stdafx.h"\r
+\r
+#include "accelerator.h"\r
+\r
+#include "cpu/image/image_mixer.h"\r
+#include "ogl/image/image_mixer.h"\r
+\r
+#include "ogl/util/context.h"\r
+\r
+#include <tbb/mutex.h>\r
+\r
+namespace caspar { namespace accelerator {\r
+ \r
+struct accelerator::impl\r
+{\r
+ const std::wstring path_;\r
+ tbb::mutex mutex_;\r
+ std::shared_ptr<ogl::context> ogl_context_;\r
+\r
+ impl(const std::wstring& path)\r
+ : path_(path)\r
+ {\r
+ }\r
+\r
+ spl::unique_ptr<core::image_mixer> create_image_mixer()\r
+ {\r
+ try\r
+ {\r
+ if(path_ == L"gpu" || path_ == L"ogl" || path_ == L"auto" || path_ == L"default")\r
+ {\r
+ tbb::mutex::scoped_lock lock(mutex_);\r
+\r
+ if(!ogl_context_)\r
+ ogl_context_.reset(new ogl::context());\r
+\r
+ return spl::make_unique<ogl::image_mixer>(spl::make_shared_ptr(ogl_context_));\r
+ }\r
+ }\r
+ catch(...)\r
+ {\r
+ if(path_ == L"gpu" || path_ == L"ogl")\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ }\r
+\r
+ return spl::make_unique<cpu::image_mixer>();\r
+ }\r
+};\r
+\r
+accelerator::accelerator(const std::wstring& path)\r
+ : impl_(new impl(path))\r
+{\r
+}\r
+\r
+accelerator::~accelerator()\r
+{\r
+}\r
+\r
+spl::unique_ptr<core::image_mixer> accelerator::create_image_mixer()\r
+{\r
+ return impl_->create_image_mixer();\r
+}\r
+\r
+}}
\ No newline at end of file
--- /dev/null
+#pragma once\r
+\r
+#include <common/forward.h>\r
+#include <common/spl/memory.h>\r
+\r
+#include <core/mixer/image/image_mixer.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+namespace caspar { namespace accelerator {\r
+ \r
+class accelerator : boost::noncopyable\r
+{\r
+public:\r
+ accelerator(const std::wstring& path);\r
+ ~accelerator();\r
+\r
+ spl::unique_ptr<core::image_mixer> create_image_mixer();\r
+private:\r
+ struct impl;\r
+ spl::unique_ptr<impl> impl_;\r
+};\r
+\r
+}}
\ No newline at end of file
</Lib>\r
</ItemDefinitionGroup>\r
<ItemGroup>\r
- <ClInclude Include="cpu\factory.h" />\r
<ClInclude Include="cpu\image\image_mixer.h" />\r
<ClInclude Include="cpu\util\xmm.h" />\r
<ClInclude Include="cpu\util\write_frame.h" />\r
- <ClInclude Include="factory.h" />\r
- <ClInclude Include="ogl\factory.h" />\r
+ <ClInclude Include="accelerator.h" />\r
<ClInclude Include="ogl\image\blending_glsl.h" />\r
<ClInclude Include="ogl\image\image_kernel.h" />\r
<ClInclude Include="ogl\image\image_mixer.h" />\r
</ProjectReference>\r
</ItemGroup>\r
<ItemGroup>\r
- <ClCompile Include="cpu\factory.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="accelerator.cpp" />\r
<ClCompile Include="cpu\image\image_mixer.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\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="ogl\factory.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="ogl\image\image_kernel.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
<ClInclude Include="cpu\util\write_frame.h">\r
<Filter>source\cpu\util</Filter>\r
</ClInclude>\r
- <ClInclude Include="factory.h">\r
- <Filter>source</Filter>\r
- </ClInclude>\r
- <ClInclude Include="cpu\factory.h">\r
- <Filter>source\cpu</Filter>\r
- </ClInclude>\r
- <ClInclude Include="ogl\factory.h">\r
- <Filter>source\ogl</Filter>\r
- </ClInclude>\r
<ClInclude Include="cpu\util\xmm.h">\r
<Filter>source\cpu\util</Filter>\r
</ClInclude>\r
+ <ClInclude Include="accelerator.h">\r
+ <Filter>source</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="StdAfx.cpp" />\r
<ClCompile Include="cpu\util\write_frame.cpp">\r
<Filter>source\cpu\util</Filter>\r
</ClCompile>\r
- <ClCompile Include="cpu\factory.cpp">\r
- <Filter>source\cpu</Filter>\r
- </ClCompile>\r
- <ClCompile Include="ogl\factory.cpp">\r
- <Filter>source\ogl</Filter>\r
+ <ClCompile Include="accelerator.cpp">\r
+ <Filter>source</Filter>\r
</ClCompile>\r
</ItemGroup>\r
</Project>
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "factory.h"\r
-\r
-#include "image/image_mixer.h"\r
-\r
-namespace caspar { namespace accelerator { namespace cpu {\r
- \r
-spl::shared_ptr<core::image_mixer> factory::create_image_mixer()\r
-{\r
- return spl::shared_ptr<cpu::image_mixer>();\r
-}\r
-\r
-}}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include "../factory.h"\r
-\r
-namespace caspar { namespace accelerator { namespace cpu {\r
- \r
-class factory : public accelerator::factory\r
-{\r
-public:\r
- virtual spl::shared_ptr<core::image_mixer> create_image_mixer() override;\r
-};\r
-\r
-}}}
\ No newline at end of file
impl() \r
: transform_stack_(1) \r
{\r
- CASPAR_LOG(info) << L"Initialized CPU Accelerated Image Mixer";\r
+ CASPAR_LOG(info) << L"Initialized Streaming SIMD Extensions Accelerated CPU Image Mixer";\r
}\r
\r
void begin_layer(core::blend_mode blend_mode)\r
+++ /dev/null
-#pragma once\r
-\r
-#include <common/forward.h>\r
-#include <common/spl/memory.h>\r
-\r
-#include <boost/noncopyable.hpp>\r
-\r
-FORWARD2(caspar, core, struct image_mixer);\r
-\r
-namespace caspar { namespace accelerator {\r
- \r
-struct factory : boost::noncopyable\r
-{\r
- virtual spl::shared_ptr<core::image_mixer> create_image_mixer() = 0;\r
-};\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "factory.h"\r
-\r
-#include "image/image_mixer.h"\r
-#include "util/context.h"\r
-\r
-namespace caspar { namespace accelerator { namespace ogl {\r
- \r
-struct factory::impl\r
-{\r
- spl::shared_ptr<context> ogl_;\r
- \r
- spl::shared_ptr<core::image_mixer> create_image_mixer()\r
- {\r
- return spl::make_shared<ogl::image_mixer>(ogl_);\r
- }\r
-};\r
-\r
-factory::factory(){}\r
-spl::shared_ptr<core::image_mixer> factory::create_image_mixer(){return impl_->create_image_mixer();}\r
-\r
-}}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include "../factory.h"\r
-\r
-#include <common/spl/memory.h>\r
-\r
-namespace caspar { namespace accelerator { namespace ogl {\r
- \r
-class factory : public accelerator::factory\r
-{\r
-public:\r
- factory();\r
-\r
- virtual spl::shared_ptr<core::image_mixer> create_image_mixer() override;\r
-private:\r
- struct impl;\r
- spl::shared_ptr<impl> impl_;\r
-};\r
-\r
-}}}
\ No newline at end of file
: ogl_(ogl)\r
, kernel_(ogl_)\r
{\r
- CASPAR_LOG(info) << L"Initialized OpenGL GPU Accelerated Image Mixer";\r
}\r
\r
boost::shared_future<boost::iterator_range<const uint8_t*>> operator()(std::vector<layer> layers, const core::video_format_desc& format_desc)\r
, renderer_(ogl)\r
, transform_stack_(1) \r
{\r
+ CASPAR_LOG(info) << L"Initialized OpenGL Accelerated GPU Image Mixer";\r
}\r
\r
void begin_layer(core::blend_mode blend_mode)\r
\r
template<typename T2, typename D2> \r
unique_ptr(unique_ptr<T2, D2>&& p, typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0) \r
- : p_(std::move(p))\r
+ : p_(p.p_.release(), p.p_.get_deleter())\r
{\r
}\r
\r
\r
#include <stdint.h>\r
\r
-FORWARD1(boost, template<typename> class unique_future);\r
+FORWARD1(boost, template<typename> class shared_future);\r
FORWARD2(caspar, core, struct write_frame);\r
FORWARD2(caspar, core, struct pixel_format_desc);\r
\r
{ \r
spl::shared_ptr<diagnostics::graph> graph_;\r
audio_mixer audio_mixer_;\r
- spl::shared_ptr<image_mixer> image_mixer_;\r
+ spl::unique_ptr<image_mixer> image_mixer_;\r
\r
std::unordered_map<int, blend_mode> blend_modes_;\r
\r
executor executor_;\r
\r
public:\r
- impl(spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer) \r
+ impl(spl::shared_ptr<diagnostics::graph> graph, spl::unique_ptr<image_mixer> image_mixer) \r
: graph_(std::move(graph))\r
, audio_mixer_()\r
, image_mixer_(std::move(image_mixer))\r
}\r
};\r
\r
-mixer::mixer(spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer) \r
+mixer::mixer(spl::shared_ptr<diagnostics::graph> graph, spl::unique_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
class mixer sealed : boost::noncopyable\r
{\r
public: \r
- explicit mixer(spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<struct image_mixer> image_mixer);\r
+ explicit mixer(spl::shared_ptr<diagnostics::graph> graph, spl::unique_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
#include <common/concurrency/lock.h>\r
#include <common/concurrency/executor.h>\r
\r
+#include <core/mixer/image/image_mixer.h>\r
+\r
#include <tbb/spin_mutex.h>\r
\r
#include <boost/property_tree/ptree.hpp>\r
\r
executor executor_;\r
public:\r
- impl(int index, const core::video_format_desc& format_desc, spl::shared_ptr<image_mixer> image_mixer) \r
+ impl(int index, const core::video_format_desc& format_desc, spl::unique_ptr<image_mixer> image_mixer) \r
: event_subject_(new monitor::subject(monitor::path() % "channel" % index))\r
, index_(index)\r
, format_desc_(format_desc)\r
}\r
};\r
\r
-video_channel::video_channel(int index, const core::video_format_desc& format_desc, spl::shared_ptr<image_mixer> image_mixer) : impl_(new impl(index, format_desc, image_mixer)){}\r
+video_channel::video_channel(int index, const core::video_format_desc& format_desc, spl::unique_ptr<image_mixer> image_mixer) : impl_(new impl(index, format_desc, std::move(image_mixer))){}\r
const stage& video_channel::stage() const { return impl_->stage_;} \r
stage& video_channel::stage() { return impl_->stage_;} \r
const mixer& video_channel::mixer() const{ return impl_->mixer_;} \r
video_channel(const video_channel&);\r
video_channel& operator=(const video_channel&);\r
public:\r
- explicit video_channel(int index, const video_format_desc& format_desc, spl::shared_ptr<image_mixer> image_mixer);\r
+ explicit video_channel(int index, const video_format_desc& format_desc, spl::unique_ptr<image_mixer> image_mixer);\r
\r
const core::stage& stage() const;\r
core::stage& stage();\r
<data-path>D:\casparcg\_data\</data-path>\r
<template-path>D:\casparcg\_templates\</template-path>\r
</paths>\r
+ <accelerator>auto [cpu|gpu|auto]</accelerator>\r
<log-level>trace</log-level>\r
<channels>\r
<channel>\r
\r
#include "server.h"\r
\r
-#include <accelerator/factory.h>\r
-#include <accelerator/ogl/factory.h>\r
-#include <accelerator/cpu/factory.h>\r
+#include <accelerator/accelerator.h>\r
\r
#include <common/env.h>\r
#include <common/except.h>\r
struct server::impl : boost::noncopyable\r
{\r
spl::shared_ptr<monitor::subject> event_subject_;\r
- std::unique_ptr<accelerator::factory> accel_factory_;\r
+ accelerator::accelerator accelerator_;\r
std::vector<spl::shared_ptr<IO::AsyncEventServer>> async_servers_; \r
std::vector<spl::shared_ptr<video_channel>> channels_;\r
\r
impl() \r
+ : accelerator_(env::properties().get(L"configuration.accelerator", L"auto"))\r
{ \r
- auto accel_str = env::properties().get(L"configuration.accelerator", L"auto");\r
-\r
- if(accel_str == L"cpu")\r
- accel_factory_.reset(new accelerator::cpu::factory());\r
- else\r
- {\r
- try\r
- {\r
- accel_factory_.reset(new accelerator::ogl::factory());\r
- }\r
- catch(...)\r
- {\r
- CASPAR_LOG_CURRENT_EXCEPTION();\r
- accel_factory_.reset(new accelerator::cpu::factory());\r
- CASPAR_LOG(warning) << L"Using fallback CPU mixer.";\r
- }\r
- }\r
\r
ffmpeg::init();\r
CASPAR_LOG(info) << L"Initialized ffmpeg module.";\r
if(format_desc.format == video_format::invalid)\r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Invalid video-mode."));\r
\r
- auto channel = spl::make_shared<video_channel>(static_cast<int>(channels_.size()+1), format_desc, accel_factory_->create_image_mixer());\r
+ auto channel = spl::make_shared<video_channel>(static_cast<int>(channels_.size()+1), format_desc, accelerator_.create_image_mixer());\r
\r
BOOST_FOREACH(auto& xml_consumer, xml_channel.second.get_child(L"consumers"))\r
{\r
\r
// Dummy diagnostics channel\r
if(env::properties().get(L"configuration.channel-grid", false))\r
- channels_.push_back(spl::make_shared<video_channel>(static_cast<int>(channels_.size()+1), core::video_format_desc(core::video_format::x576p2500), accel_factory_->create_image_mixer()));\r
+ channels_.push_back(spl::make_shared<video_channel>(static_cast<int>(channels_.size()+1), core::video_format_desc(core::video_format::x576p2500), accelerator_.create_image_mixer()));\r
}\r
\r
void setup_controllers(const boost::property_tree::wptree& pt)\r