context::register_drawable(impl_);\r
}\r
\r
-void graph::update(const std::string& name, float value){if(impl_)impl_->update(name, value);}\r
-void graph::set(const std::string& name, float value){if(impl_)impl_->set(name, value);}\r
-void graph::tag(const std::string& name){if(impl_)impl_->tag(name);}\r
-void graph::guide(const std::string& name, float value){if(impl_)impl_->guide(name, value);}\r
+void graph::update_value(const std::string& name, float value){if(impl_)impl_->update(name, value);}\r
+void graph::set_value(const std::string& name, float value){if(impl_)impl_->set(name, value);}\r
void graph::set_color(const std::string& name, color c){if(impl_)impl_->set_color(name, c);}\r
+void graph::add_tag(const std::string& name){if(impl_)impl_->tag(name);}\r
+void graph::add_guide(const std::string& name, float value){if(impl_)impl_->guide(name, value);}\r
\r
safe_ptr<graph> create_graph(const std::string& name)\r
{\r
graph(const std::string& name);\r
graph(const printer& parent_printer);\r
public:\r
- void update(const std::string& name, float value);\r
- void set(const std::string& name, float value);\r
- void tag(const std::string& name);\r
- void guide(const std::string& name, float value);\r
+ void update_value(const std::string& name, float value);\r
+ void set_value(const std::string& name, float value);\r
void set_color(const std::string& name, color c);\r
+ void add_tag(const std::string& name);\r
+ void add_guide(const std::string& name, float value);\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)\r
#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_\r
\r
+#define BOOST_PARAMETER_MAX_ARITY 7\r
+\r
#ifdef _DEBUG\r
#include <crtdbg.h>\r
#endif\r
#include <boost/filesystem.hpp>\r
#include <boost/foreach.hpp>\r
#include <boost/range/algorithm.hpp>\r
+#include <boost/signals2.hpp>\r
\r
#include <GLee.h>\r
\r
{ \r
const int index_;\r
const video_format_desc format_desc_;\r
+ \r
+ const std::shared_ptr<frame_mixer_device> mixer_;\r
+ const std::shared_ptr<frame_consumer_device> consumer_;\r
+ const std::shared_ptr<frame_producer_device> producer_;\r
\r
- std::shared_ptr<frame_consumer_device> consumer_;\r
- std::shared_ptr<frame_mixer_device> mixer_;\r
- std::shared_ptr<frame_producer_device> producer_;\r
+ boost::signals2::scoped_connection mixer_connection_;\r
+ boost::signals2::scoped_connection producer_connection_;\r
\r
public:\r
implementation(int index, const video_format_desc& format_desc) \r
: index_(index)\r
, format_desc_(format_desc)\r
, consumer_(new frame_consumer_device(std::bind(&implementation::print, this), format_desc))\r
- , mixer_(new frame_mixer_device(std::bind(&implementation::print, this), format_desc, std::bind(&frame_consumer_device::send, consumer_.get(), std::placeholders::_1)))\r
- , producer_(new frame_producer_device(std::bind(&implementation::print, this), safe_ptr<frame_factory>(mixer_), std::bind(&frame_mixer_device::send, mixer_.get(), std::placeholders::_1))) {}\r
-\r
- ~implementation()\r
+ , mixer_(new frame_mixer_device(std::bind(&implementation::print, this), format_desc))\r
+ , producer_(new frame_producer_device(std::bind(&implementation::print, this), safe_ptr<frame_factory>(mixer_))) \r
{\r
- // Shutdown order is important! Destroy all created frames to mixer before destroying mixer.\r
- CASPAR_LOG(info) << print() << " Shutting down channel.";\r
- producer_.reset();\r
- CASPAR_LOG(info) << print() << " Successfully shutdown producer-device.";\r
- consumer_.reset();\r
- CASPAR_LOG(info) << print() << " Successfully shutdown consumer-device.";\r
- mixer_.reset();\r
- CASPAR_LOG(info) << print() << " Successfully shutdown mixer-device.";\r
+ mixer_connection_ = mixer_->connect([=](const safe_ptr<const read_frame>& frame){consumer_->send(frame);});\r
+ producer_connection_ = producer_->connect([=](const std::vector<safe_ptr<draw_frame>>& frames){mixer_->send(frames);});\r
}\r
-\r
+ \r
std::wstring print() const\r
{\r
return L"channel[" + boost::lexical_cast<std::wstring>(index_+1) + L"-" + format_desc_.name + L"]";\r
model_name_ = get_card_desc(videoCardType);\r
\r
graph_ = diagnostics::create_graph(narrow(print()));\r
- graph_->guide("tick-time", 0.5);\r
+ graph_->add_guide("tick-time", 0.5);\r
graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
\r
//void* pBlueDevice = blue_attach_to_device(1);\r
}\r
\r
std::rotate(reserved_frames_.begin(), reserved_frames_.begin() + 1, reserved_frames_.end());\r
- graph_->update("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+ graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
perf_timer_.reset();\r
}\r
catch(...)\r
model_name_ = std::wstring(pModelName);\r
\r
graph_ = diagnostics::create_graph(narrow(print()));\r
- graph_->guide("tick-time", 0.5);\r
+ graph_->add_guide("tick-time", 0.5);\r
graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
\r
auto display_mode = get_display_mode(output_.p, format_desc_.format);\r
CASPAR_LOG(error) << print() << L" Failed to schedule video.";\r
\r
std::rotate(reserved_frames_.begin(), reserved_frames_.begin() + 1, reserved_frames_.end());\r
- graph_->update("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+ graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
perf_timer_.reset();\r
}\r
\r
: graph_(diagnostics::create_graph(narrow(print())))\r
, container_(5)\r
{\r
- graph_->guide("tick-time", 0.5);\r
+ graph_->add_guide("tick-time", 0.5);\r
graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
is_running_ = true;\r
}\r
data.Samples = container_.back().data();\r
data.NbSamples = container_.back().size(); \r
\r
- graph_->update("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5)); \r
+ graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5)); \r
perf_timer_.reset();\r
\r
return is_running_;\r
, graph_(diagnostics::create_graph(narrow(print())))\r
, executor_(print())\r
{ \r
- graph_->guide("frame-time", 0.5);\r
+ graph_->add_guide("frame-time", 0.5);\r
graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
}\r
\r
while(window_.GetEvent(e)){}\r
render(frame);\r
window_.Display();\r
- graph_->update("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+ graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
});\r
}\r
\r
model_name_ = std::wstring(pModelName);\r
\r
graph_ = diagnostics::create_graph(boost::bind(&decklink_input::print, this));\r
- graph_->guide("tick-time", 0.5);\r
+ graph_->add_guide("tick-time", 0.5);\r
graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
\r
unsigned long decklinkVideoFormat = GetDecklinkVideoFormat(format_desc.format);\r
// TODO: Enable audio input\r
virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame* video, IDeckLinkAudioInputPacket* audio)\r
{ \r
- graph_->update("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+ graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
perf_timer_.reset();\r
\r
if(!video)\r
\r
{\r
graph_ = diagnostics::create_graph(boost::bind(&ffmpeg_producer::print, this)); \r
- graph_->guide("frame-time", 0.5);\r
+ graph_->add_guide("frame-time", 0.5);\r
graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
}\r
\r
return last_frame_; \r
}\r
\r
- graph_->update("frame-time", static_cast<float>(perf_timer_.elapsed()/frame_factory_->get_video_format_desc().interval*0.5));\r
+ graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()/frame_factory_->get_video_format_desc().interval*0.5));\r
\r
auto result = last_frame_;\r
if(!ouput_channel_.empty())\r
else if(!loop_ || !seek_frame(0, AVSEEK_FLAG_BACKWARD)) // TODO: av_seek_frame does not work for all formats\r
executor_.stop();\r
else\r
- graph_->tag("seek");\r
+ graph_->add_tag("seek");\r
\r
boost::this_thread::yield();\r
\r
- graph_->update("input-buffer", static_cast<float>(video_packet_buffer_.size())/static_cast<float>(PACKET_BUFFER_COUNT)); \r
+ graph_->update_value("input-buffer", static_cast<float>(video_packet_buffer_.size())/static_cast<float>(PACKET_BUFFER_COUNT)); \r
\r
executor_.begin_invoke([this]{read_file();}); \r
boost::unique_lock<boost::mutex> lock(mutex_);\r
, ax_(nullptr)\r
, head_(draw_frame::empty())\r
{\r
- graph_->guide("frame-time", 0.5f);\r
+ graph_->add_guide("frame-time", 0.5f);\r
graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f)); \r
graph_->set_color("param", diagnostics::color(1.0f, 0.5f, 0.0f)); \r
graph_->set_color("underflow", diagnostics::color(0.6f, 0.3f, 0.9f)); \r
{ \r
if(!ax_->FlashCall(param))\r
CASPAR_LOG(warning) << print() << " Flash function call failed. Param: " << param << ".";\r
- graph_->tag("param");\r
+ graph_->add_tag("param");\r
\r
if(abs(ax_->GetFPS() / format_desc_.fps) > 0.001)\r
CASPAR_LOG(warning) << print() << " Invalid frame-rate: " << ax_->GetFPS() << L". Should be either " << format_desc_.fps << L" or " << format_desc_.fps*2.0 << L".";\r
safe_ptr<draw_frame> render_simple_frame(bool underflow)\r
{\r
if(underflow)\r
- graph_->tag("underflow");\r
+ graph_->add_tag("underflow");\r
\r
double frame_time = 1.0/ax_->GetFPS()*(underflow ? 0.90 : 1.0); // Reduce sync-time if in underflow.\r
timer_.tick(frame_time); // Tick doesnt work on nested timelines, force an actual sync\r
head_ = frame;\r
} \r
\r
- graph_->update("frame-time", static_cast<float>(perf_timer_.elapsed()/frame_time));\r
+ graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()/frame_time));\r
return head_;\r
}\r
};\r
if(!renderer_)\r
return draw_frame::empty();\r
\r
- graph_->set("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));\r
+ graph_->set_value("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));\r
if(!frame_buffer_.try_pop(tail_))\r
return tail_;\r
\r
auto frame = draw_frame::empty();\r
do{frame = renderer_->render_frame(frame_buffer_.size() < frame_buffer_.capacity()-2);}\r
while(frame_buffer_.try_push(frame) && frame == draw_frame::empty());\r
- graph_->set("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity())); \r
+ graph_->set_value("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity())); \r
fps_.fetch_and_store(static_cast<int>(renderer_->fps()*100.0));\r
}\r
catch(...)\r
const printer parent_printer_;\r
\r
std::map<int, layer> layers_; \r
-\r
- output_func output_;\r
-\r
+ \r
const safe_ptr<frame_factory> factory_;\r
+\r
+ output_t output_;\r
\r
mutable executor executor_;\r
public:\r
- implementation(const printer& parent_printer, const safe_ptr<frame_factory>& factory, const output_func& output) \r
+ implementation(const printer& parent_printer, const safe_ptr<frame_factory>& factory) \r
: parent_printer_(parent_printer)\r
, factory_(factory)\r
- , output_(output)\r
{\r
executor_.start();\r
- executor_.begin_invoke([=]{tick();});\r
}\r
\r
~implementation()\r
{\r
CASPAR_LOG(info) << "Shutting down producer-device.";\r
}\r
+\r
+ boost::signals2::connection connect(const output_t::slot_type& subscriber)\r
+ {\r
+ return executor_.invoke([&]() -> boost::signals2::connection\r
+ {\r
+ if(output_.empty())\r
+ executor_.begin_invoke([=]{tick();}); \r
+ return output_.connect(subscriber);\r
+ });\r
+ }\r
\r
void tick()\r
- { \r
+ { \r
+ if(output_.empty())\r
+ return; \r
+\r
output_(draw());\r
executor_.begin_invoke([=]{tick();});\r
}\r
}\r
};\r
\r
-frame_producer_device::frame_producer_device(const printer& parent_printer, const safe_ptr<frame_factory>& factory, const output_func& output) : impl_(new implementation(parent_printer, factory, output)){}\r
+frame_producer_device::frame_producer_device(const printer& parent_printer, const safe_ptr<frame_factory>& factory) : impl_(new implementation(parent_printer, factory)){}\r
frame_producer_device::frame_producer_device(frame_producer_device&& other) : impl_(std::move(other.impl_)){}\r
+boost::signals2::connection frame_producer_device::connect(const output_t::slot_type& subscriber){return impl_->connect(subscriber);}\r
void frame_producer_device::swap(frame_producer_device& other){impl_->swap(other);}\r
void frame_producer_device::load(int index, const safe_ptr<frame_producer>& producer, bool play_on_load, bool preview){impl_->load(index, producer, play_on_load, preview);}\r
void frame_producer_device::pause(int index){impl_->pause(index);}\r
\r
#include <functional>\r
\r
+#include <boost/signals2.hpp>\r
+\r
namespace caspar { namespace core {\r
\r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
class frame_producer_device : boost::noncopyable\r
{\r
public:\r
- typedef std::function<void(const std::vector<safe_ptr<draw_frame>>&)> output_func;\r
+ typedef boost::signals2::signal<void(const std::vector<safe_ptr<draw_frame>>&)> output_t;\r
+ \r
+ boost::signals2::connection connect(const output_t::slot_type& subscriber);\r
\r
- explicit frame_producer_device(const printer& parent_printer, const safe_ptr<frame_factory>& factory, const output_func& output);\r
+ explicit frame_producer_device(const printer& parent_printer, const safe_ptr<frame_factory>& factory);\r
frame_producer_device(frame_producer_device&& other);\r
void swap(frame_producer_device& other);\r
\r
# endif\r
#endif\r
\r
+#define BOOST_PARAMETER_MAX_ARITY 7\r
+\r
#ifdef _DEBUG\r
#include <crtdbg.h>\r
#endif\r
#include <boost/filesystem.hpp>\r
#include <boost/foreach.hpp>\r
#include <boost/range/algorithm.hpp>\r
+#include <boost/signals2.hpp>\r
\r
#include <GLee.h>\r
\r
{\r
for(size_t n = r.begin(); n < r.end(); ++n)\r
{\r
- double delta = static_cast<double>(n)/static_cast<double>(audio_data_.size());\r
- double sample_gain = prev_gain * (1.0 - delta) + next_gain * delta;\r
+ double alpha = static_cast<double>(n)/static_cast<double>(audio_data_.size());\r
+ double sample_gain = prev_gain * (1.0 - alpha) + next_gain * alpha;\r
int sample = static_cast<int>(audio_data[n]);\r
sample = (static_cast<int>(sample_gain*static_cast<double>(1<<15))*sample)>>15;\r
audio_data_[n] = static_cast<short>((static_cast<int>(audio_data_[n]) + sample) & 0xFFFF);\r
#include <unordered_map>\r
\r
namespace caspar { namespace core {\r
- \r
- \r
+ \r
template<typename T>\r
class basic_animated_value\r
{\r
const printer parent_printer_;\r
const video_format_desc format_desc_;\r
\r
- safe_ptr<diagnostics::graph> graph_;\r
+ safe_ptr<diagnostics::graph> diag_;\r
timer perf_timer_;\r
timer wait_perf_timer_;\r
\r
audio_mixer audio_mixer_;\r
image_mixer image_mixer_;\r
\r
- output_func output_;\r
+ output_t output_;\r
\r
std::unordered_map<int, basic_animated_value<image_transform>> image_transforms_;\r
std::unordered_map<int, basic_animated_value<audio_transform>> audio_transforms_;\r
\r
executor executor_;\r
public:\r
- implementation(const printer& parent_printer, const video_format_desc& format_desc, const output_func& output) \r
+ implementation(const printer& parent_printer, const video_format_desc& format_desc) \r
: parent_printer_(parent_printer)\r
, format_desc_(format_desc)\r
- , graph_(diagnostics::create_graph(narrow(print())))\r
+ , diag_(diagnostics::create_graph(narrow(print())))\r
, image_mixer_(format_desc)\r
- , output_(output)\r
, executor_(print())\r
{\r
- graph_->guide("frame-time", 0.5f); \r
- graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
- graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
- graph_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f)); \r
+ diag_->add_guide("frame-time", 0.5f); \r
+ diag_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\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_.start();\r
executor_.set_capacity(2);\r
CASPAR_LOG(info) << print() << L" Successfully initialized."; \r
}\r
- \r
- void send(const std::vector<safe_ptr<draw_frame>>& frames)\r
- { \r
- executor_.begin_invoke([=]\r
+\r
+ boost::signals2::connection connect(const output_t::slot_type& subscriber)\r
+ {\r
+ return output_.connect(subscriber);\r
+ }\r
+\r
+ boost::unique_future<safe_ptr<const host_buffer>> mix_image(const std::vector<safe_ptr<draw_frame>>& frames)\r
+ {\r
+ auto image = image_mixer_.begin_pass();\r
+ BOOST_FOREACH(auto& frame, frames)\r
{\r
- perf_timer_.reset();\r
- auto image = image_mixer_.begin_pass();\r
- BOOST_FOREACH(auto& frame, frames)\r
+ if(format_desc_.mode != video_mode::progressive)\r
{\r
- if(format_desc_.mode != video_mode::progressive)\r
- {\r
- auto frame1 = make_safe<draw_frame>(frame);\r
- auto frame2 = make_safe<draw_frame>(frame);\r
-\r
- frame1->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
- frame2->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
-\r
- if(frame1->get_image_transform() != frame2->get_image_transform())\r
- draw_frame::interlace(frame1, frame2, format_desc_.mode)->process_image(image_mixer_);\r
- else\r
- frame2->process_image(image_mixer_);\r
- }\r
+ auto frame1 = make_safe<draw_frame>(frame);\r
+ auto frame2 = make_safe<draw_frame>(frame);\r
+\r
+ frame1->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
+ frame2->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
+\r
+ if(frame1->get_image_transform() != frame2->get_image_transform())\r
+ draw_frame::interlace(frame1, frame2, format_desc_.mode)->process_image(image_mixer_);\r
else\r
- {\r
- auto frame1 = make_safe<draw_frame>(frame);\r
- frame1->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
- frame1->process_image(image_mixer_);\r
- }\r
+ frame2->process_image(image_mixer_);\r
}\r
- image_mixer_.end_pass();\r
-\r
- auto audio = audio_mixer_.begin_pass();\r
- BOOST_FOREACH(auto& frame, frames)\r
+ else\r
{\r
- int num = format_desc_.mode == video_mode::progressive ? 1 : 2;\r
-\r
auto frame1 = make_safe<draw_frame>(frame);\r
- frame1->get_audio_transform() = root_audio_transform_.fetch_and_tick(num)*audio_transforms_[frame->get_layer_index()].fetch_and_tick(num);\r
- frame1->process_audio(audio_mixer_);\r
+ frame1->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
+ frame1->process_image(image_mixer_);\r
}\r
- audio_mixer_.end_pass();\r
+ }\r
+ image_mixer_.end_pass();\r
+ return std::move(image);\r
+ }\r
+\r
+ std::vector<short> mix_audio(const std::vector<safe_ptr<draw_frame>>& frames)\r
+ {\r
+ auto audio = audio_mixer_.begin_pass();\r
+ BOOST_FOREACH(auto& frame, frames)\r
+ {\r
+ int num = format_desc_.mode == video_mode::progressive ? 1 : 2;\r
\r
- graph_->update("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+ auto frame1 = make_safe<draw_frame>(frame);\r
+ frame1->get_audio_transform() = root_audio_transform_.fetch_and_tick(num)*audio_transforms_[frame->get_layer_index()].fetch_and_tick(num);\r
+ frame1->process_audio(audio_mixer_);\r
+ }\r
+ audio_mixer_.end_pass();\r
+ return audio;\r
+ }\r
+ \r
+ void send(const std::vector<safe_ptr<draw_frame>>& frames)\r
+ { \r
+ executor_.begin_invoke([=]\r
+ { \r
+ diag_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+ perf_timer_.reset();\r
\r
+ auto image = mix_image(frames);\r
+ auto audio = mix_audio(frames);\r
output_(make_safe<const read_frame>(std::move(image.get()), std::move(audio)));\r
\r
- graph_->update("tick-time", static_cast<float>(wait_perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+ diag_->update_value("tick-time", static_cast<float>(wait_perf_timer_.elapsed()/format_desc_.interval*0.5));\r
wait_perf_timer_.reset();\r
\r
- graph_->set("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
+ diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
});\r
- graph_->set("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
+ diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
}\r
\r
safe_ptr<write_frame> create_frame(const pixel_format_desc& desc)\r
}\r
};\r
\r
-frame_mixer_device::frame_mixer_device(const printer& parent_printer, const video_format_desc& format_desc, const output_func& output) : impl_(new implementation(parent_printer, format_desc, output)){}\r
+frame_mixer_device::frame_mixer_device(const printer& parent_printer, const video_format_desc& format_desc) : impl_(new implementation(parent_printer, format_desc)){}\r
frame_mixer_device::frame_mixer_device(frame_mixer_device&& other) : impl_(std::move(other.impl_)){}\r
+boost::signals2::connection frame_mixer_device::connect(const output_t::slot_type& subscriber){return impl_->connect(subscriber);}\r
void frame_mixer_device::send(const std::vector<safe_ptr<draw_frame>>& frames){impl_->send(frames);}\r
const video_format_desc& frame_mixer_device::get_video_format_desc() const { return impl_->format_desc_; }\r
safe_ptr<write_frame> frame_mixer_device::create_frame(const pixel_format_desc& desc){ return impl_->create_frame(desc); } \r
#include <common/memory/safe_ptr.h>\r
#include <common/utility/printer.h>\r
\r
+#include <boost/signals2.hpp>\r
+\r
#include <functional>\r
\r
namespace caspar { namespace core {\r
class frame_mixer_device : public frame_factory\r
{\r
public:\r
- typedef std::function<void(const safe_ptr<const read_frame>&)> output_func;\r
-\r
- frame_mixer_device(const printer& parent_printer, const video_format_desc& format_desc, const output_func& output);\r
+ typedef boost::signals2::signal<void(const safe_ptr<const read_frame>&)> output_t;\r
+ \r
+ boost::signals2::connection connect(const output_t::slot_type& subscriber);\r
+ \r
+ frame_mixer_device(const printer& parent_printer, const video_format_desc& format_desc);\r
frame_mixer_device(frame_mixer_device&& other); // nothrow\r
\r
void send(const std::vector<safe_ptr<draw_frame>>& frames); // nothrow\r
#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)\r
#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_\r
\r
+#define BOOST_PARAMETER_MAX_ARITY 7\r
+\r
#ifdef _DEBUG\r
#include <crtdbg.h>\r
#endif\r
<windowed>true</windowed>\r
</ogl>\r
<audio/>\r
- <decklink>\r
+ <!--decklink>\r
<device>1</device>\r
<embedded-audio>false</embedded-audio>\r
<internal-key>false</internal-key>\r
- </decklink>\r
+ </decklink-->\r
<!--<bluefish>\r
<device>1</device>\r
<embedded-audio>true</embedded-audio>\r
</DataExecutionPrevention>\r
<TargetMachine>MachineX86</TargetMachine>\r
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>\r
+ <MapExports>false</MapExports>\r
</Link>\r
<PostBuildEvent>\r
<Command>copy $(SolutionDir)\dlls\*.dll $(OutDir)\</Command>\r
<IgnoreSpecificDefaultLibraries>LIBC.lib</IgnoreSpecificDefaultLibraries>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<GenerateMapFile>false</GenerateMapFile>\r
- <MapExports>true</MapExports>\r
+ <MapExports>false</MapExports>\r
<SubSystem>Console</SubSystem>\r
<OptimizeReferences>\r
</OptimizeReferences>\r
<IgnoreSpecificDefaultLibraries>LIBC.lib</IgnoreSpecificDefaultLibraries>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<GenerateMapFile>false</GenerateMapFile>\r
- <MapExports>true</MapExports>\r
+ <MapExports>false</MapExports>\r
<SubSystem>Console</SubSystem>\r
<OptimizeReferences>\r
</OptimizeReferences>\r
<IgnoreSpecificDefaultLibraries>LIBC.lib</IgnoreSpecificDefaultLibraries>\r
<GenerateDebugInformation>true</GenerateDebugInformation>\r
<GenerateMapFile>false</GenerateMapFile>\r
- <MapExports>true</MapExports>\r
+ <MapExports>false</MapExports>\r
<SubSystem>Console</SubSystem>\r
<OptimizeReferences>\r
</OptimizeReferences>\r