tbb::concurrent_bounded_queue<std::function<void()>> execution_queue_;\r
public:\r
\r
- explicit executor(const std::wstring& name) : name_(narrow(name)) // noexcept\r
+ explicit executor(const std::wstring& name, bool auto_start = false) : name_(narrow(name)) // noexcept\r
{\r
is_running_ = false;\r
+ if(auto_start)\r
+ start();\r
}\r
\r
virtual ~executor() // noexcept\r
{\r
execution_queue_.set_capacity(capacity);\r
}\r
+\r
+ void start() // noexcept\r
+ {\r
+ if(is_running_.fetch_and_store(true))\r
+ return;\r
+ clear();\r
+ thread_ = boost::thread([this]{run();});\r
+ }\r
\r
void stop() // noexcept\r
{\r
template<typename Func>\r
auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept\r
{ \r
- if(!is_running_)\r
- start();\r
-\r
typedef boost::packaged_task<decltype(func())> task_type;\r
\r
auto task = task_type(std::forward<Func>(func));\r
template<typename Func>\r
auto invoke(Func&& func) -> decltype(func())\r
{\r
+ if(!is_running_)\r
+ start();\r
+\r
if(boost::this_thread::get_id() == thread_.get_id()) // Avoids potential deadlock.\r
return func();\r
\r
bool is_running() const { return is_running_; } \r
\r
private:\r
-\r
- void start() // noexcept\r
- {\r
- if(is_running_.fetch_and_store(true))\r
- return;\r
- clear();\r
- thread_ = boost::thread([this]{run();});\r
- }\r
\r
void execute() // noexcept\r
{\r
private:\r
context() : executor_(L"diagnostics")\r
{\r
+ executor_.start();\r
executor_.begin_invoke([this]\r
{\r
window_.Create(sf::VideoMode(600, 1000), "CasparCG Diagnostics");\r
, executor_(L"frame_consumer_device")\r
{ \r
executor_.set_capacity(2);\r
+ executor_.start();\r
}\r
\r
void add(int index, safe_ptr<frame_consumer>&& consumer)\r
diag_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
diag_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f)); \r
executor_.set_capacity(2); \r
+ executor_.start();\r
CASPAR_LOG(info) << print() << L" Successfully initialized."; \r
}\r
\r
auto image = image_mixer_.begin_pass();\r
BOOST_FOREACH(auto& frame, frames)\r
{\r
- // Apply root transform and render.\r
if(format_desc_.mode != core::video_mode::progressive)\r
{\r
auto frame1 = make_safe<core::basic_frame>(frame.second);\r
\r
ogl_device::ogl_device() : executor_(L"ogl_device")\r
{\r
+ executor_.start();\r
invoke([=]\r
{\r
context_.reset(new sf::Context());\r
{\r
return context_->begin_invoke([=]() -> safe_ptr<const host_buffer>\r
{\r
- reading_->map(); // Open host buffer for reading.\r
- render_targets_[0]->attach(0); // Render to the next target\r
- GL(glClear(GL_COLOR_BUFFER_BIT)); // Clear the new target\r
- return make_safe(reading_);\r
+ reading_->map();\r
+ render_targets_[0]->attach(0);\r
+ GL(glClear(GL_COLOR_BUFFER_BIT));\r
+ return safe_ptr<const host_buffer>(reading_);\r
});\r
}\r
\r
{\r
context_->begin_invoke([=]\r
{\r
- reading_ = context_->create_host_buffer(format_desc_.size, host_buffer::read_only); // Create a new host buffer.\r
- render_targets_[0]->write(*reading_); // Move data to host buffer.\r
- std::rotate(render_targets_.begin(), render_targets_.begin() + 1, render_targets_.end()); // Set new render target.\r
+ reading_ = context_->create_host_buffer(format_desc_.size, host_buffer::read_only);\r
+ render_targets_[0]->write(*reading_);\r
+ std::rotate(render_targets_.begin(), render_targets_.begin() + 1, render_targets_.end());\r
});\r
}\r
\r
public:\r
implementation(const video_format_desc& format_desc) \r
: format_desc_(format_desc)\r
- , executor_(L"frame_producer_device"){}\r
+ , executor_(L"frame_producer_device")\r
+ {\r
+ executor_.start();\r
+ }\r
\r
boost::signals2::connection connect(const output_t::slot_type& subscriber)\r
{\r
\r
struct decklink_consumer::implementation\r
{\r
- std::unique_ptr<decklink_output> output_;\r
+ std::unique_ptr<decklink_output> input_;\r
size_t device_index_;\r
bool embed_audio_;\r
bool internal_key_;\r
: device_index_(device_index)\r
, embed_audio_(embed_audio)\r
, internal_key_(internal_key)\r
- , executor_(L"DECKLINK[" + boost::lexical_cast<std::wstring>(device_index) + L"]"){}\r
+ , executor_(L"DECKLINK[" + boost::lexical_cast<std::wstring>(device_index) + L"]")\r
+ {\r
+ executor_.start();\r
+ }\r
\r
~implementation()\r
{\r
executor_.invoke([&]\r
{\r
- output_ = nullptr;\r
+ input_ = nullptr;\r
});\r
}\r
\r
{\r
executor_.invoke([&]\r
{\r
- output_.reset(new decklink_output(format_desc, device_index_, embed_audio_, internal_key_));\r
+ input_.reset(new decklink_output(format_desc, device_index_, embed_audio_, internal_key_));\r
});\r
}\r
\r
void send(const safe_ptr<const core::read_frame>& frame)\r
{\r
- output_->send(frame);\r
+ input_->send(frame);\r
}\r
\r
size_t buffer_depth() const\r
\r
std::wstring print() const\r
{\r
- return output_->print();\r
+ return input_->print();\r
}\r
};\r
\r
explicit decklink_producer(const safe_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, size_t device_index)\r
: format_desc_(format_desc) \r
, device_index_(device_index)\r
- , executor_(L"decklink_producer")\r
+ , executor_(L"decklink_producer", true)\r
{\r
executor_.invoke([=]\r
{\r
void initialize(const core::video_format_desc& format_desc)\r
{\r
format_desc_ = format_desc;\r
+ executor_.start();\r
active_ = executor_.begin_invoke([]{});\r
\r
fmt_ = av_guess_format(nullptr, filename_.c_str(), nullptr);\r
#include <common/utility/timer.h>\r
#include <common/utility/assert.h>\r
\r
-#include <boost/timer.hpp>\r
-\r
#include <tbb/parallel_invoke.h>\r
\r
+#include <boost/timer.hpp>\r
+\r
#include <deque>\r
#include <functional>\r
\r
source_info(narrow(print())) << \r
msg_info("No video or audio codec context found.")); \r
\r
+ executor_.start();\r
executor_.begin_invoke([this]{read_file();});\r
CASPAR_LOG(info) << print() << " Started.";\r
}\r