]> git.sesse.net Git - casparcg/blobdiff - core/producer/separated/separated_producer.cpp
Merged most recent OSC changes
[casparcg] / core / producer / separated / separated_producer.cpp
index b316e32093745466cf1218e2ddd151973dd40d8d..6138901b034164d77aed763885074bc7fe8480f9 100644 (file)
-/*\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 flags) override\r
-       {\r
-               tbb::parallel_invoke(\r
-               [&]\r
-               {\r
-                       if(fill_ == core::basic_frame::late())\r
-                               fill_ = receive_and_follow(fill_producer_, flags);\r
-               },\r
-               [&]\r
-               {\r
-                       if(key_ == core::basic_frame::late())\r
-                               key_ = receive_and_follow(key_producer_, flags | ALPHA_ONLY_FLAG);\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 uint32_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);
+}
+
+}}
+