-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\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
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#include "../../stdafx.h"\r
-\r
-#include "separated_producer.h"\r
-\r
-#include <core/producer/frame/basic_frame.h>\r
-\r
-#include <tbb/parallel_invoke.h>\r
-\r
-namespace caspar { namespace core { \r
-\r
-struct separated_producer : public frame_producer\r
-{ \r
- safe_ptr<frame_producer> fill_producer_;\r
- safe_ptr<frame_producer> key_producer_;\r
- safe_ptr<basic_frame> fill_;\r
- safe_ptr<basic_frame> key_;\r
- safe_ptr<basic_frame> last_frame_;\r
- \r
- explicit separated_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key) \r
- : fill_producer_(fill)\r
- , key_producer_(key)\r
- , fill_(core::basic_frame::late())\r
- , key_(core::basic_frame::late())\r
- , last_frame_(core::basic_frame::empty())\r
- {\r
- }\r
-\r
- // frame_producer\r
- \r
- virtual safe_ptr<basic_frame> receive(int hints) override\r
- {\r
- tbb::parallel_invoke(\r
- [&]\r
- {\r
- if(fill_ == core::basic_frame::late())\r
- fill_ = receive_and_follow(fill_producer_, hints);\r
- },\r
- [&]\r
- {\r
- if(key_ == core::basic_frame::late())\r
- key_ = receive_and_follow(key_producer_, hints | ALPHA_HINT);\r
- });\r
-\r
- if(fill_ == basic_frame::eof() || key_ == basic_frame::eof())\r
- return basic_frame::eof();\r
-\r
- if(fill_ == core::basic_frame::late() || key_ == core::basic_frame::late()) // One of the producers is lagging, keep them in sync.\r
- return core::basic_frame::late();\r
- \r
- auto frame = basic_frame::fill_and_key(fill_, key_);\r
-\r
- fill_ = basic_frame::late();\r
- key_ = basic_frame::late();\r
-\r
- return last_frame_ = frame;\r
- }\r
-\r
- virtual safe_ptr<core::basic_frame> last_frame() const override\r
- {\r
- return disable_audio(last_frame_);\r
- }\r
-\r
- virtual int64_t nb_frames() const override\r
- {\r
- return std::min(fill_producer_->nb_frames(), key_producer_->nb_frames());\r
- }\r
-\r
- virtual std::wstring print() const override\r
- {\r
- return L"separated[fill:" + fill_producer_->print() + L"|key:" + key_producer_->print() + L"]";\r
- } \r
-\r
- boost::property_tree::wptree info() const override\r
- {\r
- boost::property_tree::wptree info;\r
- info.add(L"type", L"separated-producer");\r
- info.add_child(L"fill.producer", fill_producer_->info());\r
- info.add_child(L"key.producer", key_producer_->info());\r
- return info;\r
- }\r
-};\r
-\r
-safe_ptr<frame_producer> create_separated_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key)\r
-{\r
- return make_safe<separated_producer>(fill, key);\r
-}\r
-\r
-}}\r
-\r
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* 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 <http://www.gnu.org/licenses/>.
+*
+* Author: Robert Nagy, ronag89@gmail.com
+*/
+
+#include "../../stdafx.h"
+
+#include "separated_producer.h"
+
+#include <core/producer/frame_producer.h>
+#include <core/frame/draw_frame.h>
+#include <core/monitor/monitor.h>
+
+#include <tbb/parallel_invoke.h>
+
+namespace caspar { namespace core {
+
+class separated_producer : public frame_producer_base
+{
+ spl::shared_ptr<monitor::subject> monitor_subject_;
+ spl::shared_ptr<monitor::subject> key_monitor_subject_;
+
+ spl::shared_ptr<frame_producer> fill_producer_;
+ spl::shared_ptr<frame_producer> key_producer_;
+ draw_frame fill_;
+ draw_frame key_;
+
+public:
+ explicit separated_producer(const spl::shared_ptr<frame_producer>& fill, const spl::shared_ptr<frame_producer>& key)
+ : key_monitor_subject_(spl::make_shared<monitor::subject>("/keyer"))
+ , fill_producer_(fill)
+ , key_producer_(key)
+ , fill_(core::draw_frame::late())
+ , key_(core::draw_frame::late())
+ {
+ CASPAR_LOG(info) << print() << L" Initialized";
+
+ key_monitor_subject_->attach_parent(monitor_subject_);
+
+ key_producer_->monitor_output().attach_parent(key_monitor_subject_);
+ fill_producer_->monitor_output().attach_parent(monitor_subject_);
+ }
+
+ // frame_producer
+
+ draw_frame receive_impl() override
+ {
+ tbb::parallel_invoke(
+ [&]
+ {
+ if(fill_ == core::draw_frame::late())
+ fill_ = fill_producer_->receive();
+ },
+ [&]
+ {
+ if(key_ == core::draw_frame::late())
+ key_ = key_producer_->receive();
+ });
+
+ if(fill_ == core::draw_frame::late() || key_ == core::draw_frame::late()) // One of the producers is lagging, keep them in sync.
+ return core::draw_frame::late();
+
+ auto frame = draw_frame::mask(fill_, key_);
+
+ fill_ = draw_frame::late();
+ key_ = draw_frame::late();
+
+ return frame;
+ }
+
+ draw_frame last_frame()
+ {
+ return draw_frame::mask(fill_producer_->last_frame(), key_producer_->last_frame());
+ }
+
+ draw_frame create_thumbnail_frame()
+ {
+ auto fill_frame = fill_producer_->create_thumbnail_frame();
+ auto key_frame = key_producer_->create_thumbnail_frame();
+
+ if (fill_frame == draw_frame::empty() || key_frame == draw_frame::empty())
+ return draw_frame::empty();
+
+ if (fill_frame == draw_frame::late() || key_frame == draw_frame::late())
+ return draw_frame::late();
+
+ return draw_frame::mask(fill_frame, key_frame);
+ }
+
+ constraints& pixel_constraints() override
+ {
+ return fill_producer_->pixel_constraints();
+ }
+
+ uint32_t nb_frames() const override
+ {
+ return std::min(fill_producer_->nb_frames(), key_producer_->nb_frames());
+ }
+
+ std::wstring print() const override
+ {
+ return L"separated[fill:" + fill_producer_->print() + L"|key[" + key_producer_->print() + L"]]";
+ }
+
+ boost::unique_future<std::wstring> call(const std::vector<std::wstring>& params) override
+ {
+ key_producer_->call(params);
+ return fill_producer_->call(params);
+ }
+
+ std::wstring name() const override
+ {
+ return L"separated";
+ }
+
+ boost::property_tree::wptree info() const override
+ {
+ return fill_producer_->info();;
+ }
+
+ monitor::subject& monitor_output() { return *monitor_subject_; }
+};
+
+spl::shared_ptr<frame_producer> create_separated_producer(const spl::shared_ptr<frame_producer>& fill, const spl::shared_ptr<frame_producer>& key)
+{
+ return spl::make_shared<separated_producer>(fill, key);
+}
+
+}}
+